4

私はJavaにかなり慣れていないので、コードの一部でwait()またはを使用し、他のスレッドを引き続き実行するために、さまざまなスレッドを使用し始めています。sleep()

このプロジェクトでは、とインポートを使用JFrameしています。私がやろうとしているのは、スレッドの 1 つ (私のコードではメインの開始スレッド) を使用して、プレイヤーが三目並べボード上のスペースを選択できるようにし、それをクリックするとアイコンが変更されることです。その後、AI は 1 秒間待機してから、作成した 2 番目のスレッドから再生します。javax.swing.*java.awt.*

残念ながら、ait.sleep(1000)(aitは私のスレッド名) を呼び出すたびに、両方のスレッドが実行を終了する前に 1 秒間待機します。1 つのスレッドをスリープ状態にすると実行全体が停止する理由を誰か教えてもらえますか?

4

4 に答える 4

15

1つのスレッドをスリープすると実行全体が停止する理由を誰かに教えてもらえますか

Swing GUIが、他のコードが実行されるスレッドとは別の独自の特別なスレッドで作成されることをよりよく説明するために、これはブロック内にSwingコンポーネントを作成することによって行われます(これを行っていない場合でも、GUIは初期スレッドと呼ばれる単一のスレッド)。これで、オンのときに(または同じように)単に電話をかけると、電話が終了するのを待ちます。これで、すべてのSwingイベントがEDTで処理されるため、呼び出しによって実行を一時停止し、UIイベントの処理を一時停止します。したがって、GUIはフリーズします(戻るまで)。main()SwingUtilities.invokeXXXsleepEvent Dispatch ThreadThreadThread.sleepsleep(..)sleep(..)

Thread.sleep(..)UIがフリーズしているように見えるため、 on Event Dispatch Thread(またはThreadスリープによって不要な実行ブロックが発生する場所)は使用しないでください。

Thread.sleep(..)これは、 GUIのEDTを呼び出すことによって引き起こされるこの望ましくない動作を正確に示す良い例です

むしろ使用:

  • スイングタイマーの例:

    int delay=1000;// wait for second
    
    Timer timer = new Timer(delay, new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            //action that you want performed 
        }
    });
    //timer.setRepeats(false);//the timer should only go off once
    timer.start();
    
  • スイングワーカー

または、Swingコンポーネントが作成/変更されていない場合:

  • TimerTask

  • スレッド、次に使用しますThread.sleep(int milis)(ただし、いずれの場合もIMOの最後のオプションです)

アップデート

Swing Timer/SwingWorkerはJava1.6でのみ追加されましたが、より長い正弦のJava1.3とJDK1がそれぞれ使用されているため、上記の2つのメソッドのいずれかを使用して、Swingコンポーネントをブロックで作成/操作する呼び出しをラップすることもできTimerTaskます。それは物事が行われていた方法です:PThreadSwingUtilities/EventQueue#invokeXX

于 2012-12-28T19:04:48.617 に答える
3

Thread.sleep静的メソッドです。与えられた任意の参照を介してそれを呼び出すことThreadは、単に便利な形です。

その結果、 の呼び出しsleepは実際sleepには現在のを呼び出してThreadいます。これは、あなたの場合はイベント スレッドであると思われます。イベント スレッドでスリープ/ブロックすると、ロックされているように見えます。

于 2012-12-28T19:28:01.980 に答える
2

スレッドをスリープ状態にする場合は、そのaitスレッドをスリープ状態にするようにコーディングします。あるスレッドが別のスレッドに「到達」し、それを低レベルで押し出す設計は、根本的に壊れています。すべてのスレッドのコードを作成するので、最初に実行したいことを実行するようにコードを作成して、外部からコードにアクセスする必要がないようにします。

台所にいる人が朝食の作り方を知っているのか、寝室にいる人が怒鳴って朝食を作る各ステップを実行するように指示するのか、どちらがより理にかなっていますか?確かに、あなたは彼らに朝食を作るように言うかもしれません。しかし、あなたは間違いなく各ステップを低レベルで指示しません。

于 2012-12-28T19:04:14.733 に答える
1

Thread.sleep現在実行中のスレッドを指定された時間スリープさせる静的メソッドですJava 構文では、変数を介して静的メソッドを呼び出すことができますが、コンパイラは単にその変数のコンパイル時の型を使用して、呼び出すメソッドを決定します。

Thread ait = null;
ait.sleep(1000); // calls Thread.sleep(1000), causing current thread to sleep.
                 // In particular, does *not* NPE

またwait()、これは静的ではなくインスタンスメソッドですが、現在のスレッドに待機をさせます(ait.wait(1000)現在のスレッドを最大1秒または別のスレッドが呼び出すまで待機させますait.notifyAll())。

あるスレッドが別のスレッドを制御できるようにするために、Java の初期の頃に導入されたThread.suspend()とそれに対応resume()するものがありますが、それらは本質的にデッドロックが発生しやすいため、すぐに廃止されました。あるスレッドに別のスレッドを「制御」させたい場合に推奨されるパターンは、協調的に行うことです。つまり、スレッド A が設定し、スレッド B が読み取るある種の共有フラグを持ち、フラグに従って B がスリープ状態になるようにします

volatile boolean threadBShouldRun = true;

// Thread B
while(true) {
  if(threadBShouldRun) {
    // do some stuff
  } else {
    Thread.sleep(1000);
  }
}

// Thread A
if(someCondition) {
  threadBShouldRun = false;
}

java.util.concurrentしかし、一般的には、パッケージに含まれている機能を利用する方が簡単で、エラーが発生しにくくなります。マルチスレッドを正しく実行することは、見た目よりもはるかに困難です。

于 2012-12-28T19:29:59.927 に答える