Java 输入侦听器应该同步吗?

Java 输入侦听器应该同步吗?,java,synchronization,keylistener,Java,Synchronization,Keylistener,下面发布的示例代码显示了两个类。一个实现KeyListener,另一个实现Runnable,并在无限循环中运行,每20毫秒休眠一次。当按下一个键时,以int形式表示的keyChar用作设置布尔数组的索引true或false,表示是否按下该键。同时,进程循环正在搜索键数组的真值或假值,并将真值设置为假,然后打印出字符。我的问题是,我是否需要使用使用锁的同步来访问charArray,因为它在两个线程中使用:进程线程和密钥侦听器线程 示例代码: import java.awt.Component; i

下面发布的示例代码显示了两个类。一个实现KeyListener,另一个实现Runnable,并在无限循环中运行,每20毫秒休眠一次。当按下一个键时,以int形式表示的keyChar用作设置布尔数组的索引true或false,表示是否按下该键。同时,进程循环正在搜索键数组的真值或假值,并将真值设置为假,然后打印出字符。我的问题是,我是否需要使用使用锁的同步来访问charArray,因为它在两个线程中使用:进程线程和密钥侦听器线程

示例代码:

import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Input implements KeyListener {

public boolean[] charArray;

public Input(Component component) {
    charArray = new boolean[127];
    component.addKeyListener(this);
}

@Override
public void keyPressed(KeyEvent e) {
            (possible synchronization with a lock?)
    int keyChar = e.getKeyChar();
    if (keyChar == 27 || keyChar == 9 || keyChar == 10 || keyChar == 127) //useless keys like del, tab, esc, etc..
        keyChar = 65535;
    if (keyChar < 65535) //65535 represents no true char value
        charArray[keyChar] = true;
}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void keyTyped(KeyEvent e) {
}
}




import java.awt.Dimension;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class Process extends JFrame implements Runnable {

private boolean running;
private Input input;

public Process() {
    running = false;
    input = new Input(this);
    setTitle("Keyboard Test");
    setSize(new Dimension(200, 200));
    toFront();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
}

/**
 * @param args
 */
public static void main(String[] args) {
    new Process().startThread();
}

public synchronized void startThread() {
    running = true;
    new Thread(this).start();
}

@Override
public void run() {
    while (running) {
                    (possible synchronization with a lock?)
        for (int i = 0; i < input.charArray.length; i++) {
            if (input.charArray[i] == true) {
                input.charArray[i] = false;
                System.out.println((char) i);
            }
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
        }
    }
}
}
导入java.awt.Component;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
公共类输入实现KeyListener{
公共布尔[]字符;
公共输入(组件){
charArray=新布尔值[127];
addKeyListener(这个);
}
@凌驾
按下公共无效键(按键事件e){
(可能与锁同步?)
int keyChar=e.getKeyChar();
if(keyChar==27 | | keyChar==9 | | keyChar==10 | | keyChar==127)//像del、tab、esc等无用的键。。
keyChar=65535;
if(keyChar<65535)//65535不表示真正的字符值
charArray[keyChar]=真;
}
@凌驾
公共无效密钥已释放(密钥事件e){
}
@凌驾
public void keyTyped(KeyEvent e){
}
}
导入java.awt.Dimension;
导入javax.swing.JFrame;
@抑制警告(“串行”)
公共类进程扩展JFrame实现可运行{
私有布尔运行;
私人投入;
公共程序(){
运行=错误;
输入=新输入(本);
设置标题(“键盘测试”);
设置尺寸(新尺寸(200200));
toFront();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(真);
}
/**
*@param args
*/
公共静态void main(字符串[]args){
新进程().startThread();
}
公共同步的void startThread(){
运行=真;
新线程(this.start();
}
@凌驾
公开募捐{
(跑步时){
(可能与锁同步?)
for(int i=0;i
您的
charArray
变量至少从两个线程(进程中启动的线程和输入类中的EDT)访问,因此您需要同步这些访问以确保可见性(即确保一个线程所做的更改从另一个线程可见)

请注意,代码中还有几个其他问题,例如:

  • 在构造过程中,不应让这种情况消失(通过调用
    input=new input(this)
    component.addKeyListener(this)
    ),这可能会导致多线程环境中的奇怪行为
  • 您应该尝试在
    进程
    类中使用
    JFrame
    变量,而不是扩展
    JFrame
  • 我不确定您打算如何将
    running
    设置为false,但在
    run
    方法中没有关于该变量的同步,因此您可能不会看到它变为false

当涉及AWT或Swing时,首要规则是永远不要同步或以其他方式干扰调度线程。如果您不熟悉这一点,请查看

在您的例子中,我将把非GUI线程功能完全分离为一个单独的类,并在必要时使用java.util.concurrent中真正有用的类之一在两者之间进行通信

如果由于线程问题而导致锁定或延迟,并且实际上处于调度线程中,整个GUI将冻结