我是java中并发和线程的新手,我有以下场景-
Function1(从队列中获取下一个任务并用task调用function2(,然后Function2(调用Function Run来运行此任务(,然后运行(函数运行是使用具有固定线程池的执行器服务提交任务,代码如下(
ExecutorService exeService = Executors.newFixedThreadPool(3);
private void run(Task task){
Abstract batchExecutor = getBatchExecutor(param1,param2, param3, param4, task);
Future<Void> future = exeService.submit(batchExecutor);
while (!future.isDone()) {
if (isStopRequested.get()) {
try {
future.get(5, TimeUnit.MINUTES);
} catch (TimeoutException e) {
e.printStackTrace();
}
throw new InterruptedException("message");
}
Thread.sleep(3000);
}
future.get();
Map<String, Result> submittedObjects = batchExecutor.getSubmittedObjects();
storeSubmittedObjects(submittedObjects);
}
我的问题是,即使在声明了线程池之后,任务仍然以顺序的方式运行。我如何使它并行,以便一旦有另一个对运行的调用,它就应该使用池中的空闲线程并提交任务
所有这些函数都没有返回类型。
run(Task task)
方法在末尾包含future.get();
:这意味着您的当前线程将阻塞,直到提交的操作完成。所以,若在同一个线程中对run(Task task)
进行3次调用,则所有3个任务都将按顺序执行,而不是并行执行。
如何正确处理这一问题取决于您如何构建应用程序。如果你不提交大量的任务,你可以通过以下方法返回未来:
private Future<Void> run(Runnable task){
Abstract batchExecutor = getBatchExecutor(param1,param2, param3, param4, task);
return exeService.submit(batchExecutor);
}
然后稍后扫描结果:
ArrayList<Future<Void>> pending = new ArrayList<>();
pending.add(run(task1));
pending.add(run(task2));
pending.add(run(task3));
// ...
// clean up background tasks
for (Future<?> fut : pending)
{
fut.get();
}
请注意,如果不使用将来的结果,则可以省略收集pending
和上面的循环。只需确保您的应用程序在所有任务完成后关闭执行器队列:
exeService.shutdown();
exeService.awaitTermination(365, TimeUnit.DAYS);
如果您需要在每个任务之后执行后处理,那么run(Task)
方法应该更改为使用exeService.submit(Callable<SomeResult - such as Abstract>)
并返回Future<SomeResult>
,以便稍后在调用线程中执行后续操作。