0

我是java中并发和线程的新手,我有以下场景 -

Function1(从队列中获取下一个任务并使用任务调用 function2)然后 Function2(调用 Function Run 以运行此任务)然后 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);
        }

我的问题是即使在声明线程池之后,任务仍然以顺序方式运行。我怎样才能让它并行,以便一旦有另一个运行调用它应该使用池中的空闲线程并提交任务?

所有这些函数都没有返回类型。

4

1 回答 1

2

run(Task task)方法future.get();最后包含:这意味着您当前的线程将阻塞,直到提交的操作完成。因此,如果您在同一个线程中进行 3 次调用,run(Task task)则所有 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>,以便您稍后可以在调用线程中执行后续操作。

于 2022-01-19T16:20:39.650 回答