0

現在、多数のボタンを含む Swing-Interface を備えた小さなアプリケーションを作成しています。今私の問題は次のとおりです。アプリケーションを起動した後、2 つのボタンが押されるのを待ってから通常どおりに処理するメソッドが呼び出されます。2 つのスレッドがあります。1 つはメイン スレッドで、もう 1 つは 2 つのボタンが押されるまで待機するためだけに作成されます。ボタンについては、変数を 1 ずつ増やし、変数が 2 のときにもう一方の変数を起動するメソッドを呼び出す、いつものように ActionListener を追加しました。
だからここに私のコードがあります:

int counter = 0;
static Thread thread1;
static Thread thread2;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                thread1 = new Thread() {
                    @Override
                    public void run() {
                        MainFrame frame = new MainFrame();
                        frame.setVisible(true);
                        start();
                    }
                };
                thread1.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public MainFrame() {
    //other stuff and similar Listeners
    JButton button1 = new JButton();
    button1.addActionListener(new ActionAdapter() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            count++;
            notifyIfTwo();
        }
    });
}

public void notifyIfTwo() {
    if (count == 2) {
        synchronized(thread2) {
            notifyAll();
        }
    }
}

public void start() {
    thread2 = new Thread() {
        @Override
        public void run() {
            try {
                synchronized(thread1) {
                    thread2.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    thread2.start();    
    //other stuff
}

どうやっても、私はいつも IllegalMonitorStateException を受け取ります。カウンターがまだ2かどうかを確認するthread2内のループでも試しましたが、同じ結果が得られました。同期の問題と関係があると思いますが、私はマルチスレッド全体に慣れていないので、正しい方向への指針を教えていただければ幸いです。
それとも、「2 つのボタンが押されるまで待つ」という問題全体を行う簡単な方法を知っているでしょうか?

よろしくお願いし
ます。

4

4 に答える 4

3

を使用しCountDownLatchます。countDown()指定された数の呼び出しを待機できます。

Thread.wait();あなたのコードでは意味がありません。コンパイルできませんでした。メソッドは、wait同期しているオブジェクトに適用できます。

于 2013-03-21T12:31:08.107 に答える
1

ポイントはこれです:

    synchronized(thread2) {
        notifyAll();
    }

を待機しているすべてのスレッドに通知してthisいますが、 のモニターがありませんthis。すべての wait/notify/notifyAll について、コードは次のようにする必要があります。

 synchronized (foo) {
    foo.wait();    // or foo.notify()
 }

同様に、後で次のようになります。

  synchronized(thread1) {
     thread2.wait();
  }

obj1 == obj2 でない限り、obj1 で同期して obj2 で待機することはできません。

于 2013-03-21T12:36:31.207 に答える
1

例外の原因は、thread1 が UI スレッドから GUI コンポーネントにアクセスしていることだと思います。これにアプローチする 1 つの方法は、thread1 を取り除くことです。onClick (または actionPerformed) ハンドラーに変数をインクリメントさせます。thread2 をループさせ、待機後に変数の値を監視します (たとえば、500 ミリ秒)。

したがって、実行可能なものを使用して呼び出しを後で保持できますが、次のように外側の実行メソッドで作業を行います。

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
    public void run() {
        try
        {
            MainFrame frame = new MainFrame();
            frame.setVisible(true);
            start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});
}

public void start() {
thread2 = new Thread() {
    @Override
    public void run() {
        try {
                while (keepGoing)
                {
                    thread2.sleep(500);
                    if (variableIncremented)
                    {
                        // doSomething();
                        // reset variable, or set keepGoing = false
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};
    thread2.start();    
    //other stuff
}
于 2013-03-21T12:30:57.037 に答える
0

わかりました、今それを理解しました。残りの問題は、GUIスレッドとロジックを含む他のスレッドを(投稿したコードの外で)厳密に分離しなかったことです。
IllegalMonitorStateExceptionを理解するのを手伝ってくれたすべての人に感謝します。
私は今、誰かが提案したようにCountDownLatchを使用しましたが、それは魅力のように機能します。

于 2013-03-21T14:18:34.900 に答える