簡體   English   中英

java線程之間的通信:當一個線程完成其任務時停止所有線程

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM