假设我们有两个执行器,1和2。
我们可以配置在执行
时使用哪个执行程序CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(()-> {return 1;}, executor1) //executor1
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(()-> {return 2;}, executor1) //executor1
CompletableFuture<Integer> cf3 = CompletableFuture.supplyAsync(()-> {return 3;}, executor2) //executor2
但是哪个线程执行器使用CompletableFuture静态方法allOf?
CompletableFuture.allOf(cf1, cf2, cf3)
谢谢!
答案 0 :(得分:4)
没有与CompletableFuture#allOf
相关联的执行程序,它只生成CompletableFuture
,它将等待在您调用CompletableFuture#get()
的同一个线程中完成依赖项。
在您的示例中,cf1
和cf2
后面的任务仍将由executor1
执行,cf2
中的任务将由executor2
执行, allOf(..).get()
的结果将在当前线程中返回,并且不会在场景后面启动其他线程。
以下是示例,您可以通过在System.out.println行上设置断点并检查活动线程列表来了解IDE中的实际行为。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import static java.util.concurrent.CompletableFuture.supplyAsync;
public class ExecutorTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Executor executor1 = Executors.newSingleThreadExecutor();
Executor executor2 = Executors.newSingleThreadExecutor();
CompletableFuture<Integer> cf1 = supplyAsync(run(1), executor1); //executor1
CompletableFuture<Integer> cf2 = supplyAsync(run(2), executor1); //executor1
CompletableFuture<Integer> cf3 = supplyAsync(run(3), executor2); //executor2
CompletableFuture<Void> result = CompletableFuture.allOf(cf1, cf2, cf3);
new Thread(() -> {
try {
result.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}).start();
System.out.println("Waiting now...");
}
private static Supplier<Integer> run(int result) {
return () -> runDelayed(result);
}
private static int runDelayed(int result) {
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
}
答案 1 :(得分:4)
The answer of Ivan Gammel并不确切。
确实没有与CompletableFuture
返回的allOf()
相关联的执行程序,事实上,没有任何执行程序与任何CompletableFuture
相关联。
任务与执行程序关联,因为它在其中运行,但关联是反向的:执行程序有一个要执行的任务列表。
任务也可以与CompletableFuture
相关联,它将在任务完成时完成。 CompletableFuture
本身不会保留对用于创建它的任务或执行程序的引用。但是,它可以保留对依赖阶段中使用的任务和可选执行器的引用。
CompletableFuture
返回的allOf()
将由任务完成,该任务是原始CompletableFuture
的依赖阶段。在您的示例中,此任务可以通过以下方式执行:
executor1
,如果第三个任务先完成; executor2
,如果第一个任务在第三个任务之前完成;或allOf()
之前完成所有任务。通过在thenRun()
电话中添加一个从属allOf()
阶段可以看出这一点:
public class CompletableFutureAllOfCompletion {
private ExecutorService executor1 = Executors.newFixedThreadPool(2);
private ExecutorService executor2 = Executors.newFixedThreadPool(2);
private Random random = new Random();
public static void main(String[] args) {
new CompletableFutureAllOfCompletion().run();
}
public void run() {
CompletableFuture<Integer> cf1 = supplyAsync(this::randomSleepAndReturn, executor1);
CompletableFuture<Integer> cf2 = supplyAsync(this::randomSleepAndReturn, executor1);
CompletableFuture<Integer> cf3 = supplyAsync(this::randomSleepAndReturn, executor2);
randomSleepAndReturn();
CompletableFuture.allOf(cf1, cf2, cf3)
.thenRun(() -> System.out.println("allOf() commpleted on "
+ Thread.currentThread().getName()));
executor1.shutdown();
executor2.shutdown();
}
public int randomSleepAndReturn() {
try {
final long millis = random.nextInt(1000);
System.out.println(
Thread.currentThread().getName() + " waiting for " + millis);
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
}
pool-1-thread-1 waiting for 937
pool-1-thread-2 waiting for 631
main waiting for 776
pool-2-thread-1 waiting for 615
allOf() commpleted on pool-1-thread-1
pool-1-thread-1 waiting for 308
pool-1-thread-2 waiting for 788
main waiting for 389
pool-2-thread-1 waiting for 863
allOf() commpleted on pool-2-thread-1
pool-1-thread-1 waiting for 168
pool-1-thread-2 waiting for 292
main waiting for 941
pool-2-thread-1 waiting for 188
allOf() commpleted on main