簡體   English   中英

ExecutorService 由多個線程執行單個任務 n 次(n 個線程“競爭”)

[英]ExecutorService to execute a single task n times by multiple threads (n thread “races”)

我需要由多個線程執行單個任務,這樣當第一個線程完成並且在任何其他線程完成之前,所有線程都將停止並重新開始相同的任務。 這應該執行n次。

我的嘗試是使用Callable<V>和方法invokeAny() (這就是我使用集合的原因)但不確定如何實現目標。

ExecutorService executor = Executors.newFixedThreadPool(10);
Callable<String> task = () -> {
    someTask();
    return "";
};
Set<Callable<String>> tasks = new HashSet<>();
IntStream.range(0, n).forEach(i -> {
    tasks.add(task);
    executor.submit(task);
});

如何完成這個? 或任何更好的解決方案?

這是一個建議:

class Task implements Callable<Integer> {

    private final static Random RND = new Random();

    @Override
    public Integer call() throws Exception {
        try {
            // Work on task for a random duration
            Thread.sleep(RND.nextInt(5000));
        } catch (InterruptedException e) {
            System.err.println("I was interrupted."
                    + "Someone else probably solved the task before me.");
            return -1;
        }

        // Return some dummy value
        return RND.nextInt();
    }
}

class Scratch {
    public static void main(String[] args) throws InterruptedException {

        final int numWorkers = 3; // number of tasks to run in parallel

        ExecutorService executor = Executors.newFixedThreadPool(numWorkers);

        // Solve task 5 times. (Change it to while (true) { ...} if you like.)
        for (int i = 0; i < 5; i++) {

            CompletionService<Integer> completionService =
                    new ExecutorCompletionService<>(executor);

            Future<?>[] futures = new Future<?>[numWorkers];
            for (int j = 0; j < numWorkers; j++) {
                futures[j] = completionService.submit(new Task());
            }

            Future<Integer> firstToComplete = completionService.take();

            try {
                Integer result = firstToComplete.get();
                System.err.println("We got a result: " + result);
            } catch (ExecutionException e) {
                // Should not happen. Future has completed.
            }

            // Cancel all futures (it doesn't matter that we're cancelling
            // the one that has already completed).
            for (int j = 0; j < numWorkers; j++) {
                futures[j].cancel(true);
            }
        }

        executor.shutdown();
    }
}

如果您正在解決的任務不響應中斷,則將true傳遞給cancel(...)將無濟於事。 在這種情況下,我建議您進行以下更改:

  1. 在外部for循環中創建一個AtomicBoolean done變量。
  2. 將其傳遞給Task的構造函數並將其保存在Task的字段中。
  3. 在任務解決過程中,經常檢查done標志,如果donetrue則取消嘗試。
  4. 不要在第一個結果出現后對任務調用cancel ,而是將done設置為true並等待其他線程返回。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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