[英]ExecutorService to execute a single task n times by multiple threads (n thread “races”)
I need to execute a single task by multiple threads, such that when the first thread finishes and before any other thread finishes, all the threads are stopped and start the same task all over again.我需要由多个线程执行单个任务,这样当第一个线程完成并且在任何其他线程完成之前,所有线程都将停止并重新开始相同的任务。 This should be performed n times.
这应该执行n次。
My attempt is using Callable<V>
and the method invokeAny()
(that is why I use the set) but not sure how to accomplish the goal.我的尝试是使用
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);
});
How to finish this?如何完成这个? or any better solution?
或任何更好的解决方案?
Here's one suggestion:这是一个建议:
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();
}
}
If the task you're solving does not respond to interrupts, passing true
to cancel(...)
won't help.如果您正在解决的任务不响应中断,则将
true
传递给cancel(...)
将无济于事。 In that case I'd suggest you do the following changes:在这种情况下,我建议您进行以下更改:
AtomicBoolean done
variable in the outer for
loop.for
循环中创建一个AtomicBoolean done
变量。Task
and save it in a field in Task
.Task
的构造函数并将其保存在Task
的字段中。done
flag ever so often, and cancel the attempt if done
is true
.done
标志,如果done
为true
则取消尝试。cancel
on the tasks after the first result is in, set done
to true
and wait for the other threads to return.cancel
,而是将done
设置为true
并等待其他线程返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.