如何解决ExecutorService通过多个线程执行单个任务n次n个线程“竞赛”
我需要由多个线程执行单个任务,这样,当第一个线程完成并且在任何其他线程完成之前,所有线程都将停止并重新开始同一任务。这应该执行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(...)
不会有帮助。在这种情况下,建议您进行以下更改:
- 在外部
AtomicBoolean done
循环中创建一个for
变量。 - 将其传递给
Task
的构造函数,并将其保存在Task
的字段中。 - 在任务解决过程中,经常检查
done
标志,如果done
为true
,则取消尝试。 - 将第一个结果放入之后,不要在任务上调用
cancel
,而是将done
设置为true
,然后等待其他线程返回。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。