Java 可完成的未来:若干任务
如何使用5个CompletableFutures异步执行20个可运行任务(或1个任务20次) 这就是我得到的:Java 可完成的未来:若干任务,java,java-8,runnable,java-threads,completable-future,Java,Java 8,Runnable,Java Threads,Completable Future,如何使用5个CompletableFutures异步执行20个可运行任务(或1个任务20次) 这就是我得到的: Runnable task = () -> { long startTime = System.currentTimeMillis(); Random random = new Random(); while (System.currentTimeMillis() - startTime < 3000) {
Runnable task = () -> {
long startTime = System.currentTimeMillis();
Random random = new Random();
while (System.currentTimeMillis() - startTime < 3000) {
DoubleStream.generate(() -> random.nextDouble())
.limit(random.nextInt(100))
.map(n -> Math.cos(n))
.sum();
}
System.out.println("Done");
};
for (int i = 0; i < 4; i++) {
CompletableFuture<Void> future1 = CompletableFuture.runAsync(task);
CompletableFuture<Void> future2 = CompletableFuture.runAsync(task);
CompletableFuture<Void> future3 = CompletableFuture.runAsync(task);
CompletableFuture<Void> future4 = CompletableFuture.runAsync(task);
CompletableFuture<Void> future5 = CompletableFuture.runAsync(task);
future1.get();
future2.get();
future3.get();
future4.get();
future5.get();
}
Runnable任务=()->{
long startTime=System.currentTimeMillis();
随机=新随机();
而(System.currentTimeMillis()-startTime<3000){
DoubleStream.generate(()->random.nextDouble())
.限值(随机.下一个(100))
.map(n->Math.cos(n))
.sum();
}
系统输出打印项次(“完成”);
};
对于(int i=0;i<4;i++){
CompletableFuture1=CompletableFuture.runAsync(任务);
CompletableFuture2=CompletableFuture.runAsync(任务);
CompletableFuture3=CompletableFuture.runAsync(任务);
CompletableFuture4=CompletableFuture.runAsync(任务);
CompletableFuture5=CompletableFuture.runAsync(任务);
未来1.获取();
未来2.获取();
未来3.获取();
未来4.获得();
未来5.获得();
}
如果执行此代码,我可以看到它只异步运行3个future.get():
3,然后在1 for()迭代中剩下的2
因此,我希望尽可能异步地完成所有20个任务您可以使用allOf将多个任务同时作为一个任务运行。首先,我创建了5个任务的组合(与您的问题相同),但后来我添加了10个任务(只运行了两次),得到了一半的执行时间
for (int i = 0; i < 2; i++) {
CompletableFuture<Void> future1 = CompletableFuture.runAsync(task);
CompletableFuture<Void> future2 = CompletableFuture.runAsync(task);
// and so on until ten
CompletableFuture<Void> future10 = CompletableFuture.runAsync(task);
CompletableFuture<Void> combined = CompletableFuture.allOf(future1, future2, future3, future4, future5, future6, future7, future8, future9, future10);
combined.get();
}
for(int i=0;i<2;i++){
CompletableFuture1=CompletableFuture.runAsync(任务);
CompletableFuture2=CompletableFuture.runAsync(任务);
//以此类推,直到十点
CompletableFuture10=CompletableFuture.runAsync(任务);
CompletableFuture合并=CompletableFuture.allOf(future1、future2、future3、future4、future5、future6、future7、future8、future9、future10);
combined.get();
}
将以下系统属性设置为希望公共分叉连接池使用的线程数:
java.util.concurrent.ForkJoinPool.common.parallelism
看
原因是,在构建可完成的未来时,您没有指定自己的fork-join池,因此它隐式地使用
ForkJoinPool.commonPool()
请参见CompletableFuture的默认执行器是
ForkJoinPool
的公共池,该池的默认目标并行度与CPU核数减1相匹配。因此,如果您有四个内核,最多可以异步执行三个作业。因为您每5个作业强制等待一次完成,所以您将得到三个并行执行,然后在每个循环迭代中有两个并行执行
如果您想要获得一个特定的执行策略,比如您选择的并行性,最好的方法是指定一个正确配置的执行器。然后,您应该让执行器管理并行性,而不是在循环中等待
ExecutorService pool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 20; i++) {
CompletableFuture.runAsync(task, pool);
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS); // wait for the completion of all tasks
但当您的工作不涉及I/O或任何其他类型的等待响应时。释放CPU后,没有必要创建比CPU内核更多的线程。配置为处理器数量的池更可取
ExecutorService pool = Executors.newWorkStealingPool(
Runtime.getRuntime().availableProcessors());
// schedule 20 jobs at return when all completed
pool.invokeAll(Collections.nCopies(20, Executors.callable(task)));
pool.shutdown();
在您的特殊情况下,这可能会运行得较慢,因为当线程比内核多时,作业会使用系统时间来显示运行得更快,但实际执行的工作会更少。但是对于普通的计算任务,这将提高性能。也许下面的帖子有帮助:为什么关机后要等待终止?你不应该先等终止后再给执行人打电话关机吗?@FarazDurrani执行人不会关机,除非被告知这样做。因此,当没有人请求关闭时,等待终止只会等待指定的时间而没有任何好处。
ExecutorService pool = Executors.newCachedThreadPool();
// schedule 20 jobs and return when all completed
pool.invokeAll(Collections.nCopies(20, Executors.callable(task)));
pool.shutdown();
ExecutorService pool = Executors.newWorkStealingPool(
Runtime.getRuntime().availableProcessors());
// schedule 20 jobs at return when all completed
pool.invokeAll(Collections.nCopies(20, Executors.callable(task)));
pool.shutdown();