输入监听器应该同步吗?

我在下面发布的示例代码显示了两个类。 一个实现了KeyListener,另一个实现了Runnable,并且每20毫秒就会在一个无限循环中运行。 当按下一个键时,keyChar(以int的forms)用作索引,设置布尔数组的索引为true或false,表示是否按下了键。 同时,进程循环在键数组中搜索其真值或假值,并将true值设置为false,然后打印出char。 我的问题是我是否需要使用锁来访问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) { } } } } 

您的charArray变量至少从两个线程(您在Process中启动的线程和Input类中的EDT)访问,因此您需要同步这些访问以确保可见性(即确保一个线程所做的更改从另一个线程可见线)。

请注意,您的代码中还有其他一些问题,例如:

  • 你不应该在构造期间让它逃脱(通过调用input = new Input(this)component.addKeyListener(this) ) – 这可能导致multithreading环境中的奇怪行为
  • 你应该尝试在Process类中使用JFrame变量而不是扩展JFrame
  • 我不确定你打算如何将running设置为false,但是在run方法中没有围绕该变量的同步,所以你可能看不到它变为false。

当谈到AWT或Swing时,头号规则是不要同步或以其他方式干扰调度线程。 如果您对此不熟悉,请查看Dispatch Thread Issues

在您的情况下,我将非GUI线程function完全分离到一个单独的类中 – 并使用java.util.concurrent中真正有用的类之一在必要时在两者之间进行通信。

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