2014-11-05 68 views
2

我想要一個啓動線程的類並提供方法來暫停和繼續此線程。我的第一個方法是擁有標誌,只要值爲真,它就會循環睡眠方法。像這樣:如何用wait()和notify()正確地暫停線程

public class Bot { 
private Thread t ; 
private boolean isPaused; 

public Bot(){ 
    t = new Thread(new Runnable(){ 
     @Override 
     public void run() { 
      while (true) { 
       System.out.println("Hi"); 


       while(isPaused){ 
        try { 
         Thread.sleep(200); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
    }); 

    t.start(); 
} 
public void pauseBot(){ 
    isPaused = true; 
} 

public void continueBot(){ 
    isPaused = false; 
} 
} 

但由於線程仍在運行和浪費CPU,我不覺得這是一個很好的解決方案。這與wait()和notify()看起來如何? 我看過關於該主題的各種教程,但不知怎的,我不能將它們應用於我的問題。

每當我嘗試它,我要麼IllegalMonitorStateException或代碼停止我的整個應用程序,而不僅僅是我想要停止的線程。

我的另一個問題是:如何防止線程在關鍵時刻暫停,例如,

Runnable r = new Runnable(){ 

    @Override 
    public void run() { 
     while(true){ 
      task1(); 
      task2(); 

      //Thread mustn't be stopped from here.... 
      task3(); 
      task4(); 
      task5(); 
      task6(); 
      task7(); 
      //... to here 

      task8(); 
      task9(); 
      task10(); 
     } 

    } 

}; 

因爲當TASK3().... task7()處理的東西,而線程暫停時必須有辦法讓螺紋瓶口task7(),直到它暫停將到期。

我希望你能幫我解決我的問題。 由於提前, 弗洛

+0

的可能重複[?如何停止和Java中安全地恢復線程(http://stackoverflow.com/questions/11856287/how-to-stop-and-resume-thread-safely-in-java) – Anshul 2014-11-05 18:47:37

回答

2

因此,考慮這是你的Thread類:

public class MyThread extends Thread 
{ 

首先,你需要一個鎖定對象。這個對象可以是一切,如果你使用一個現有的對象,這會佔用更少的內存。如果機器人應該暫停,也定義一個標誌。

public Object lock = this; 
    public boolean pause = false; 

現在,定義爲線程一個pause()continue()方法。這設置了pause標誌。

public void pause() 
    { 
     pause = true; 
    } 

    public void continue() 
    { 
     pause = false; 

在這裏你需要喚醒線程。請注意鎖定對象上的同步,以便您不會收到IllegalMonitorStateException

 synchronized (lock) 
     { 
      lock.notifyAll(); 
     } 
    } 

不,請定義一個方法,在應該暫停時自動暫停該線程。您可以在線程可以暫停時隨時調用它。

private void pauseThread() 
    { 
     synchronized (lock) 
     { 
      if (pause) 
       lock.wait(); // Note that this can cause an InterruptedException 
     } 
    } 

現在,你可以在run()方法定義線程:

public void run() 
    { 
     task1(); 
     task2(); 

     pauseThread(); 

     task3(); 
     task4(); 
     task5(); 
     task6(); 
     task7(); 

     pauseThread(); 

     task8(); 
     task9(); 
     task10(); 
    } 
} 
+0

「這可能是一切」是什麼意思? – 2014-11-05 20:25:20

+0

@jameslarge這可以是任何對象,只要線程調用'wait()'和'notify()'方法 – msrd0 2014-11-05 20:38:47

+0

對我來說這也很奇怪。我只是不明白爲什麼你必須創建一個新的對象,只用於同步。你不能只用「this」來代替。 對不起,但我想我需要一些關於什麼是同步對象的背景信息。 謝謝你的答案btw – flxh 2014-11-05 21:19:41

相關問題