我在下面发布的示例代码显示了两个类。一个实现了KeyListener,另一个实现了Runnable,并且每20毫秒就会在一个无限循环中运行。当按下一个键时,keyChar(以int的形式)被用作索引,设置布尔数组的索引为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) {
}
}
}
}
答案 0 :(得分:1)
当谈到AWT或Swing时,头号规则是不要同步或以其他方式干扰调度线程。如果您对此不熟悉,请查看Dispatch Thread Issues
在您的情况下,我将非GUI线程功能完全分离到一个单独的类中 - 并使用java.util.concurrent中真正有用的类之一在必要时在两者之间进行通信。
如果由于线程问题导致锁定或延迟,并且您实际上在Dispatch Thread中,整个GUI将冻结
答案 1 :(得分:0)
您的charArray
变量至少从两个线程(您在Process中启动的线程和Input类中的EDT)访问,因此您需要同步这些访问以确保可见性(即确保通过从另一个线程中可以看到一个线程。)
请注意,您的代码中还有其他一些问题,例如:
input = new Input(this)
或component.addKeyListener(this)
) - 这可能导致多线程环境中的奇怪行为JFrame
课程中设置Process
变量,而不是扩展JFrame
running
设置为false,但您的run
方法中的该变量没有同步,因此您可能看不到它变错。