关于CompletableFuture功能,如果有人知道它没有动态创建多个线程。为此,我在下面的代码中尝试使用executorService但是executorService有一个固定的线程池,因此它进入阻塞状态。 您可以根据以下代码动态实现多线程中的CompletableFuture吗?
private static CompletableFuture<Integer> createCompletableFuture(ByteArrayOutputStream baOS, int totalBytes,
List<FileUploadMultiLocator> fileUploadList) {
CompletableFuture<Integer> futureCount = CompletableFuture.supplyAsync(
() -> {
try {
// simulate long running task
for (FileUploadMultiLocator fileUploadMultiLocator : fileUploadList) {
System.out.println(Thread.currentThread().getName() + " secondary task is called");
fileUploadMultiLocator.baOS.write(baOS.toByteArray(), 0, totalBytes);
fileUploadMultiLocator.setTotalBytes(totalBytes);
new Thread(fileUploadMultiLocator).start();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (Exception e) { }
return 20;
});
return futureCount;
}
答案 0 :(得分:0)
我认为你应该让事情更简单。我认为你应该在主线程中遍历你的列表,而不是在一个异步任务中创建N个线程,并且对于每个元素,创建一个completableFuture,给它你的&# 34; FileUploadMultiLocator&#34;可运行。每个可完成的未来都是Java公共fork-join池中的异步任务。
但是,如果要控制用于任务的线程数,可以使用CompletableFuture.runAsync(Runnable r, Executor e)。这样,您可以使用所需数量的线程准备一个线程池(使用Executors class中的静态方法,并将其用于您的工作。
请注意,您可以在java中使用其他工具。您也可以选择以下两种解决方案之一:
如果你可以使用Java 8,你应该使用Stream power。您可以阅读更多相关信息here。
总之,这些流允许您并行浏览/处理对象集合。对于您的示例,我将使用以下方法:
// Specify the wanted number of parallel tasks, and create a thread pool accordingly.
final int threadNb = 4;
final ForkJoinPool pool = new ForkJoinPool(threadNb);
// We give the entire procedure to the thread pool, which will be in charge of managing executions
pool.submit(
// Ask to execute each runnable in the list, in a parallel way.
() -> fileUploadList.parallelStream().forEach(r -> r.run())
);
// Below block is in charge of waiting complete execution.
pool.shutdown();
try {
pool.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
// Do whatever cancelling logic you want, or let it propagate
}
但是,您不必使用流,您可以直接使用执行程序服务。为什么你应该使用这种方法而不是自己创建线程?in the following answer:
final List<Runnable> fileUploadList = null;
// Specify the wanted number of parallel tasks.
final int threadNb = 4;
ExecutorService threadPool = Executors.newFixedThreadPool(threadNb);
for (final Runnable r : fileUploadList) {
// ... Do your pre-computing here ...
// Now, submit asynchronous part of your task for execution
threadPool.submit(r);
}
// Below block is in charge of waiting complete execution.
threadPool.shutdown();
try {
threadPool.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
// Do whatever cancelling logic you want, or let it propagate
}
另外,请注意,我在这里创建了一个on-shot执行器服务。但是,常见的做法是在应用程序的某个位置创建它,并使其保持活动状态,这样您就可以多次重复使用它的线程。在这种情况下,我给你的代码是错误的等待完成&#39;部分,您应该监控每个任务的未来。
最后一件事:我的例子非常简化用例。我既没有管理错误也没有按任务超时,因此在使用之前需要进行精炼。但是,我希望它有所帮助!