0

我在下面发布的示例代码显示了两个类。一个实现 KeyListener,另一个实现 Runnable,并在每 20 毫秒休眠一次的无限循环中运行。当一个键被按下时,keyChar,它是一个int的形式,被用作一个索引,设置一个布尔数组的索引是真还是假,表示该键被按下与否。同时,进程循环在键数组中搜索其真值或假值,并将真值设置为假,然后打印出字符。我的问题是我是否需要使用锁来使用同步来访问 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) {
        }
    }
}
}
4

2 回答 2

1

对于 AWT 或 Swing,第一条规则是永远不要同步或以其他方式干扰调度线程。如果您对此不熟悉,请查看Dispatch Thread Issues

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

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

于 2013-02-17T19:21:02.950 回答
0

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

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

  • 你不应该在构造过程中让这个逃脱(通过调用input = new Input(this)or component.addKeyListener(this)) - 这可能会导致多线程环境中的奇怪行为
  • 你应该尝试JFrame在你的类中有一个变量Process而不是扩展JFrame
  • 我不确定您打算如何设置running为 false,但是您的run方法中没有围绕该变量进行同步,因此您可能看不到它变为 false。
于 2013-02-17T19:18:45.670 回答