2

マルチスレッドを使用して、単純なサーモスタットをシミュレートしようとしています。lblDesiredTemp に保存した希望の温度値と、現在の温度 lblCurrentTemp を表示する別のラベルがあります。この問題は、システムにアクティブなスレッドが 2 つ以上ある場合に発生します。待機中のスレッドは起きません!

これは私の方法です:

'private synchronized void ApplySetting()
    {
        Thread tempetureUpdater = new Thread() 
             {
                @Override
                public synchronized void run() 
                {
                    txtLog.setText(txtLog.getText() + "\n" + this.getName());
                    try 
                    {
                        while(!isDone)
                            this.wait();
                    } 
                    catch (InterruptedException ex) 
                    {
                        txtLog.setText(txtLog.getText() + "\n" + ex.getMessage());
                    }

int Max = Integer.parseInt(lblDesiredTemp.getText()); int Current = Integer.parseInt(lblCurrentTemp.getText()); txtLog.setText(txtLog.getText() + "\n" + Current + " to " + Max); if(Current > Max) { isDone = false; for (int i = Current; i > Max; i--) { lblGasStatus.setText("Off"); try { Thread.sleep(3000); decreaseTemeture(); } catch (InterruptedException ex) { txtLog.setText(txtLog.getText() + "\n" + ex.getMessage()); } } txtLog.setText(txtLog.getText() + "\n" + this.getName() + " done!"); isDone = true; this.notifyAll(); } else { isDone = false; for (int i = Current; i < Max; i++) { lblGasStatus.setText("On"); try { Thread.sleep(3000); increaseTemeture(); } catch (InterruptedException ex) { txtLog.setText(txtLog.getText() + "\n" + ex.getMessage()); } } txtLog.setText(txtLog.getText() + "\n" + this.getName() + " done!"); isDone = true; this.notifyAll(); } // Report the result using invokeLater(). SwingUtilities.invokeLater(new Runnable() { @Override public void run() { setEnabled(true); } }); } }; tempetureUpdater.start(); }

どうしたの?!

4

3 に答える 3

4

この問題は、システムにアクティブなスレッドが 2 つ以上ある場合に発生します。待機中のスレッドは起きません!

さて、あなたは彼らにどのように期待しますか?新しいスレッドである「現在の」オブジェクトにのみ通知しています。1 つのスレッドが終了すると、 が呼び出されますが、他のスレッドthis.notifyAllは起動しません。

さらに、これをどのように書いているかについて、他のことを変更することを強くお勧めします。

  • このサイズの匿名内部クラスは、適切な名前付きクラスに分割されることを切望しています
  • メソッド名は、ApplySettingJava 命名規則に従っていません。さまざまな変数名も同様です。
  • 一般に、拡張するのは悪い考えです。代わりにThread実装し、スレッド コンストラクターにRunnable渡します。Runnable
  • オブジェクトに対してwaitand notify/notifyAllを呼び出すべきではありません。ThreadThread
  • 一般に、他のコードが同期やシグナリングに使用しないプライベート参照で同期することをお勧めします
  • マルコの回答で述べたように、ほとんどの場合、runメソッドを同期させるのは悪い考えです。前の箇条書きを考えると、メソッド全体を同期するのではなく、メソッド内の個々の参照を同期することを好みます
  • 非 UI スレッド内で UI 要素を更新しようとしているようです。私はそれが失敗すると信じています。( を使用する必要がありますinvokeLater)
于 2012-07-15T07:08:25.693 に答える
0

runメソッドを としてマークしないでくださいsynchronized。ここだけでなく、ずっと。また、notifyAll実行中のスレッドそのものを起動しようとします。これは機能しません。

于 2012-07-15T07:05:07.553 に答える
0

andのthis参照を変更して、匿名クラスのオブジェクトではなく、外側のオブジェクトを参照するようにする必要があります。これは、 andを書くのと同じくらい簡単です。ここで、はメソッドが見つかったクラスです。this.wait()this.notifyAll()ThreadMyClass.this.wait()MyClass.this.notifyAll()MyClassapplySettings

ただし、Jon Skeet によってリストされた変更を行うこともお勧めします。

于 2012-07-15T07:28:12.510 に答える