2011-12-09 173 views
1

我想製作一種方法,可以安全地停止循環中運行的線程,允許在將控制權返回到制動器之前完成最後一個循環。等待線程循環完成

現在,無論我嘗試什麼,我都會凍結。可能出於僵局或什麼; Java並不是我慣常的環境,所以這可能是另一個等待/通知問題。

boolean isRunning = true; 

@Override 
public void run() { 
    super.run(); 

    while (isRunning) { 
     // Do work... 
    } 

    synchronized(this) { 
     this.notify(); 
    } 
} 

public void stopSafely() { 
    isRunning = false; 

    try { 
     synchronized(this) { 
      this.wait(); 
     } 
    } catch (InterruptedException ex) { 
     // Handle... 
    } 
} 

這種方法(除了事實上,我上同步this,但它例如簡單起見)的問題是,如果notifywait之前調用,調用者將凍結。

我確定玩​​環繞的塊可以解決問題,但我似乎無法得到正確的組合。

有什麼想法?

回答

2

只是去真正簡單的解決方案:

private volatile boolean isRunning = true; 

@Override 
public void run() { 
    while (isRunning) { 
     // Do work... 
    } 
} 

public void stopThread() { 
    isRunning = false; 
} 

這基本上是Thread.interrupted()內部做,所以你可以用這個也:

在這種情況下
@Override 
public void run() { 
    while (Thread.interrupted()) { 
     // Do work... 
    } 
} 

你必須調用interrupt()在線程上。

0

找到一個更簡單的解決方案,這樣的變化時,它只是從檢查isRunning阻止:

boolean isRunning = true; 

@Override 
public void run() { 
    while (true) { 
     synchronized(this) { 
      if (!isRunning) break; 
     } 

     // Do work... 
    } 
} 

public void stopSafely() { 
    synchronized(this) { 
     isRunning = false; 
    } 
} 
+0

如果你保留這個,使用私有同步stopSafely(){isRunning = false;}這是更簡單和等效。 – Snicolas

+0

但是,像你一樣同步整個運行方法並不是一個好主意。 – Snicolas

+0

正如所寫,這將阻止任何呼叫stopSafely,不是? –

1

我希望第二個方法是從不同的線程調用了一個與run方法。我敢打賭。

在這種情況下,將isRunning = false放入synchronized塊中就足夠了。只有一個線程可以進入在給定監視器上同步的塊。

順便說一下,不要調用super.run(),這是沒用的,不是一個好的編程習慣。

0

首先讓make isRunning變化。

volatile boolean isRunning = true; 

的問題是,Java運行時做一些優化和價值不是體現在其他線程,即使第一個線程改變的價值。