您可以使用 ExecutorSerive.invokeAll(List<Callable<T>> tasks, long timeout, TimeUnit timeUnit)
方法(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#invokeAll-java.util.Collection-)。请看以下代码示例:
package com.github.wololock;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
final class ExecutorsServiceInvokeAnyExample {
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
final ExecutorService executor = Executors.newFixedThreadPool(5);
final List<Callable<String>> tasks = Arrays.asList(
() -> {
debug("This task runs for 1 second");
Thread.sleep(1000);
debug("Task completed!");
return "1";
},
() -> {
debug("This task runs for 2 seconds");
Thread.sleep(2000);
debug("Task completed!");
return "2";
},
() -> {
debug("This task runs for 3 seconds");
Thread.sleep(2999);
debug("Task completed!");
return "3";
},
() -> {
debug("This task runs for 4 seconds");
Thread.sleep(4000);
debug("Task completed!");
return "4";
},
() -> {
debug("This task runs for 5 seconds");
Thread.sleep(5000);
debug("Task completed!");
return "5";
}
);
try {
final List<Future<String>> result = executor.invokeAll(tasks, 3, TimeUnit.SECONDS);
if (result.stream().anyMatch(Future::isCancelled)) {
throw new RuntimeException("All tasks were not completed...");
}
} finally {
executor.shutdown();
}
}
private static void debug(String msg) {
System.out.println("[" + Thread.currentThread().getName() + "] " + msg);
}
}
我们正在使用5个任务触发
invokeAll
,其中最快的需要1秒完成,而最慢的需要5秒才能完成。调用超时设置为3秒,并且在此期间仅有3个任务将完成。在这个例子中,如果没有完成所有任务,我会抛出一个
RuntimeException
- 这取决于您的业务情况,如果出现这种情况,您会怎么做。以下是运行此示例的示例输出:
[pool-1-thread-2] This task runs for 2 seconds
[pool-1-thread-1] This task runs for 1 second
[pool-1-thread-4] This task runs for 4 seconds
[pool-1-thread-3] This task runs for 3 seconds
[pool-1-thread-5] This task runs for 5 seconds
[pool-1-thread-1] Task completed!
[pool-1-thread-2] Task completed!
[pool-1-thread-3] Task completed!
Exception in thread "main" java.lang.RuntimeException: All tasks were not completed...
如果我设置6秒的超时时间,那么所有操作都将在规定时间内完成并且不会抛出异常。
[pool-1-thread-1] This task runs for 1 second
[pool-1-thread-5] This task runs for 5 seconds
[pool-1-thread-4] This task runs for 4 seconds
[pool-1-thread-2] This task runs for 2 seconds
[pool-1-thread-3] This task runs for 3 seconds
[pool-1-thread-1] Task completed!
[pool-1-thread-2] Task completed!
[pool-1-thread-3] Task completed!
[pool-1-thread-4] Task completed!
[pool-1-thread-5] Task completed!
Process finished with exit code 0
编辑:任务超时 ≠ 数据库服务器超时
还有一件事情你需要非常仔细地考虑。正如你在问题中提到的,你的任务将执行MySQL查询。请记住,如果你的任务终止了,这并不意味着查询执行已停止——这只意味着服务器在那5-6秒钟内没有响应,但很可能查询仍在执行。在这种情况下,你可能会做出错误的假设,认为任务未完成,而实际上MySQL服务器查询已经执行,但没有结果返回给你的任务。另外一件事是,在这种情况下,你失去了对提交事务到数据库的控制,这在你的情况下可能非常关键。我希望这能帮助你更好地理解如何解决你的问题。祝你好运!