[英]Communication between java threads: stopping all threads when one finishes its task
我有n個並行運行的線程,每個線程都有一些自定義邏輯。 但是,我的要求是當任何線程完成執行時,所有其他線程應該停止執行並返回。
實現這個的最佳方法是什么? 我想通過擁有一個共享的布爾變量來做到這一點。 當任何線程完成執行時,它將設置布爾值。 所有線程都定期讀取此變量,並在設置時退出。
此外,我的自定義邏輯是一個無限循環,一旦我知道其他一些線程已經完成執行,我想在當前迭代后停止執行。
這樣做的正確方法是什么?
使用ExecutorService
及其.invokeAny()
方法(注意:還有一個帶超時的版本)。
來自Javadoc:
執行給定的任務,返回已成功完成的任務的結果(即,不拋出異常),如果有的話。
一個是你的結果, .shutdown()
執行者。
請參閱Executors
類以獲取符合您需求的執行程序。
另一個解決方案是ExecutorCompletionService
類; 在這種情況下,您使用.take()
而不是.invokeAny()
,並且必須逐個提交每個任務。 而且你還必須保留對ExecutorService
的引用,因為你需要一個作為參數,並且還需要關閉它。
(注意:如果你沒有返回結果,請Callable<
Void
>
實例)
我更喜歡使用通用信號量來控制執行,並經常檢查線程。
public class MyTask implements Runnable {
private static volatile boolean isDone = false
@Override
public void run() {
while(true) {
if (isDone) {
break;
}
// do some calculation, no wait() s
if (...has result...) {
isDone = true;
break;
}
}
}
}
Thread t1 = new Thread(new MyTask());
Thread t2 = new Thread(new MyTask());
Thread t3 = new Thread(new MyTask());
t1.start();
t2.start();
t3.start();
您必須注意的唯一事情是static volatile boolean
變量。 靜態因為所有線程都必須訪問相同的標志, volatile才能阻止JVM緩存其數據。 如果不將其標記為volatile,編譯器可能會產生這樣的字節碼,它會從一個領域優化讀取這樣一種方式,它會讀取場只有一次,並使用每個循環執行的保存價值。
如果您的任務不同並且實現了不同的循環,則可以使用任何外部public static volatile boolean
字段來保存標志。
此解決方案不依賴於線程的等待狀態。 您可以在循環中檢查isDone
多個位置(甚至在每個代碼塊之前)。 如果您保證您的代碼將進行退出檢查,則無需中斷線程。
看,你可以在所有Thread對象上保持共享的全局數組,然后在每個任務結束時,你可以執行一個“清理”函數的調用,該函數只接受所有這些對象並對它們執行“中斷”調用。 這將導致第一個線程完成以完成其余的執行。
public class MyMain
{
public static Thread workers[NUM_WORK];
public static void main(..)
{
MyMain.workers[0] = new Thread(new MyTask0());
.
.
.
MyMain.workers[n] = new Thread(new MyTaskN());
//Then start them all..
// And wait for them unless you want them to die before execution ;)
}
}
然后是你的其他工人
import MyMain;
public class MyTaskI implements Runnable
{
public void run()
{
//Do all the work
for(Thread t : MyMain.workers)
{
// If it is not this thread
t.interrupt();
}
}
}
對不起,如果我發出任何語法錯誤。 自從我做Java以來已經有一段時間了,我的想法就是你明白了這一點;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.