0

My sample code posted below shows two classes. One implements KeyListener and the other implements Runnable and is running in an infinite loop sleeping every 20 ms. When a key is pressed the keyChar, which is in the form of an int, is used as an index setting the index of a boolean array true or false, representing with the key was pressed or not. At the same time the process loop is searching the key array for its true or false values and setting the true ones false then printing out the char. My question is whether or not I need to use synchronization using a lock for accessing the charArray because it is used in two threads: the process thread and the key listener thread.

Sample Code:

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 の非常に便利なクラスの 1 つを使用して 2 つの間で通信します。

スレッドの問題が原因でロックまたは遅延が発生し、実際に Dispatch Thread にいる場合、GUI 全体がフリーズします。

于 2013-02-17T19:21:02.950 に答える
0

変数charArrayは少なくとも2つのスレッド(Processで開始したスレッドとInputクラスのEDT)からアクセスされるため、これらのアクセスを同期して可視性を確保する必要があります(つまり、一方のスレッドによって行われた変更がもう一方のスレッドから見えるようにします)。

コードには他にもいくつかの問題があることに注意してください。次に例を示します。

  • input = new Input(this)構築中にこれをエスケープさせないでください(またはを呼び出すことによってcomponent.addKeyListener(this))-これは、マルチスレッド環境で奇妙な動作を引き起こす可能性があります
  • 拡張するのではなく、クラスJFrame内に変数を含めるようにしてくださいProcessJFrame
  • どのようにfalseに設定するかはわかりませんが、メソッドrunning内のその変数の周りに同期がないため、falseになることはないかもしれません。run
于 2013-02-17T19:18:45.670 に答える