2013-05-26 9 views
25

私はスレッドについて読んだことを述べていますが、私は決して使ったことはありません。 だから私はあなたに尋ねる:)スレッドを一時停止してから再開する方法はありますか?

私は2件のスレッドがあります。ABAはGUIを管理し、Bはロジックを管理します。

私はAで始まります。

次に、AがGUIを描画したときに、実行メソッドにポイントXに達するまでBを待つようにします。

BがXポイントインランメソッドに達したら、Bを一時停止し、Aを再開します。

ABシェアGUIを管理するためのいくつかの変数、およびロジック...

は、私はそれを行うことができますか?はいの場合、どうですか? :)

+1

はい、できます。これは基本的なスレッドの演習です。しようとすると、失敗した場合、私たちはここに助けてくれるでしょう:) – Maroun

+3

複数のスレッドを持つ背後にある考え方は、複数のスレッドを並行して実行させることによって明示的にそれらを一時停止/公正でバランスのとれた方法でCPU時間のスライスを与えられます。 (特に、GUIスレッドを一時停止しないようにして、GUIが常に応答するようにする必要があります)はい、実行できますが、私はあなたが必要とは思わないでしょう。 – Patashu

+0

ただのメモです。スイングは単一のスレッド環境です。つまり、UI要素のすべての相互作用と変更をイベントディスパッチスレッドのコンテキストで行う必要があります。 Swingはスレッドセーフではありません。つまり、EDT以外のスレッドからUI要素を試したり、更新したり、作成したりしてはいけません。スウィングの使用を想定してください。 – MadProgrammer

答えて

14

wait()notify()方法の使用:

待ち()は - 別のスレッドが 通知()メソッド、またはこの目的のためのnotifyAll()メソッドを呼び出すまで、現在のスレッドを待機させます。

notify() - このオブジェクトのモニタで待機している1つのスレッドを起動します。

+4

'semaphore'は、' synchronized'と 'wait' /' notify'によくある落とし穴を避けるためにお勧めします。 –

4

GUIスレッドを一時停止する必要はありません。オペレーティングシステムがそれを処理し、ユーザーが何かをした場合に応答する準備ができている必要があります。

もう1つの考えは、共有変数が2つのスレッド間で正しく同期されていることを確認することです。私は最近、その質問に答えることを試みた、hereを参照してください。

3

CountDownLatchを使用できます。スレッドAがスレッドBがcountDownLatchInstance.await();を呼び出すのを待たなければならないとき、BがXポイントに達すると、countDownLatchInstance.countDown()が呼び出されます。 Aはその実行フローを継続することができます。

あなたは

AはGUI

を管理して言うとき、私はスレッドを中断し、再開するためにJavaプリミティブ

+0

個人的には、 'CountDownLatch'ではなく、' CountDownLatch'を再利用することができないので 'Semaphore'を推奨します... –

0

、あなたがUI/Main Thread

を参照しないことを望みます推奨されません。あなたはあなたが必要なものを最高を達成することができますどのように把握するために、これを参照してください - あなたは私がThread.suspendThread.resumeの代わりに使用する必要がありますどのような&履歴書

を一時停止と同等のものを行うことができますどのようにhttp://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html チェック!

Thread.stopと同様に、賢明なアプローチは、スレッドの目的の状態(アクティブまたはサスペンド)を示す変数を「ターゲットスレッド」にポーリングさせることです。目的の状態が中断されると、スレッドはObject.waitを使用して待機します。スレッドが再開されると、Object.notifyを使用してターゲットスレッドに通知されます。

例コードは、これを達成するのに役立つ同じ回答です。

6

オブジェクトクラスのwaitnotifyメソッドを使用してスレッドをブロックすることはできますが、正しく行うにはややこしいことがあります。ここでのRunnableで無限ループ内の例です:

public class Example implements Runnable {  
    private volatile boolean running = true; 
    private volatile boolean paused = false; 
    private final Object pauseLock = new Object(); 

    @Override 
    public void run() { 
     while (running){ 
      synchronized (pauseLock) { 
       if (!running) { // may have changed while waiting to 
           // synchronize on pauseLock 
        break; 
       } 
       if (paused) { 
        try { 
         pauseLock.wait(); // will cause this Thread to block until 
              // another thread calls pauseLock.notifyAll() 
              // Note that calling wait() will 
              // relinquish the synchronized lock that this 
              // thread holds on pauseLock so another thread 
              // can acquire the lock to call notifyAll() 
              // (link with explanation below this code) 
        } catch (InterruptedException ex) { 
         break; 
        } 
        if (!running) { // running might have changed since we paused 
         break; 
        } 
       } 
      } 
      // Your code here 
     } 
    } 

    public void stop() { 
     running = false; 
     // you might also want to interrupt() the Thread that is 
     // running this Runnable, too, or perhaps call: 
     resume(); 
     // to unblock 
    } 

    public void pause() { 
     // you may want to throw an IllegalStateException if !running 
     paused = true; 
    } 

    public void resume() { 
     synchronized (pauseLock) { 
      paused = false; 
      pauseLock.notifyAll(); // Unblocks thread 
     } 
    } 
}; 

(私たちはwaitnotifyAllを呼び出しながら、上に示したよう同期させる必要がある理由の詳細については、the Java tutorial on the subjectを参照してください。)

別のスレッドがこれを呼び出す場合Runnableのpause()メソッドを使用すると、whileループの先頭に到達するとrunnableを実行するスレッドがブロックされます。

任意の時点でスレッドを一時停止することはできません。スレッドが必要な場合は、一時停止してブロックする必要があるかどうか定期的にチェックする必要があります。

+0

pauseLock、resumeメソッドと同期しているので、待ち時間は決して通知されません。上記はデッドロックになります –

+2

@DrBDOAdams 'wait'と' notify'は必ず** synchronized'ブロックで呼び出さなければなりません。 [ここ](http:// stackoverflow。com/questions/2779484/why-must-wait-always-be-in-synchronized-block)および[ここ](https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)を参照してください。実際には、別の方法で試してみると 'IllegalMonitorStateException'がスローされます。 'wait()'が呼び出されると、現在のスレッドはそのオブジェクトに保持されているロックを放棄し、他のスレッドがそのスレッドを獲得できるようにします。 – megaflop

+1

このクラスは 'Thread'を拡張しないので、' interrupt(); '(あるいは' Thread.interrupt(); ')を呼び出すのは間違っています。それは 'resume();'の呼び出しでなければなりませんか? –

1
私は、スレッドの待機を得た方法です

と私のために働い通知:

public class Main { 

public static void main(String[] args) { 

    final Object lock = new Object(); 


    MyThread t = new MyThread(); 
    t.lock = lock; 
    t.run(); 

    while(true){ 
     try { 
      synchronized (lock) { 
       lock.wait(); 
      } 
      System.out.println("hello"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     }    
    }  
} 

}

パブリッククラスMyThreadは、いつでも、次にスレッド{

Object lock; 

@Override 
public void run(){ 

    JFrame fr = new JFrame("Anothing"); 
    JButton btn = new JButton("Next"); 
    btn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      synchronized (lock) { 
       lock.notify(); 
      } 

     } 
    }); 
    fr.setLayout(new FlowLayout()); 
    fr.add(btn); 
    fr.setSize(400, 400); 
    fr.setVisible(true); 
} 

}

を拡張します私はボタンを押して、他のスレッドが目を覚まし、1ラウンドを実行し、新しいCLIを待つcking。