假设我们有两个执行人,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)
谢啦!
没有与CompletableFuture#allOf相关联的执行器,它只会生成CompletableFuture,它将在同一个线程中等待依赖项的完成,您将在该线程中调用CompletableFuture#get()。
在您的示例中,cf1和cf2后面的任务仍将由执行器1执行,cf2中的任务将由执行器2执行,这是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;
}
}
伊凡·加梅尔的答案并不准确。
实际上,没有与allOf()返回的CompletableFuture相关联的执行器,因为事实上,从来没有与任何CompletableFuture相关联的执行器。
任务与执行程序相关联,因为它在其中运行,但关联是反向的:执行程序有一个要执行的任务列表。
任务还可以与可完成的未来相关联,该未来将在任务完成时完成。CompletableFuture本身不保留对用于创建它的任务或执行器的引用。然而,它可以保留对任务的引用,并可以选择在依赖阶段中使用的执行器。
由allOf()返回的CompletableFuture将由任务完成,该任务是原始CompletableFuture的从属阶段。在您的示例中,此任务可以通过以下方式执行:
这可以通过向allOf()
调用添加依赖的thenRun()
阶段来看出:
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
由于无法保证将使用的执行器,因此对其中一个方法的调用之后应该是异步(,executor)调用,以控制将使用哪个执行器。
如果需要返回其中一个调用的结果CompletableFuture,只需添加一个applyasync(i-
我在某个存储库类上有一个方法,它返回。完成这些期货的代码使用一个第三方库来阻止。我打算有一个单独的有界,这个存储库类将使用它来进行这些阻塞调用。 这里有一个例子: 我的应用程序的其余部分将组成这些期货,并用结果做一些其他的事情。当提供给、、等的其他函数时,我不希望它们在存储库的上运行。 另一个例子: JavaDoc声明: 为非异步方法的从属完成提供的操作可以由完成当前CompletableFutu
在阅读关于流的留档时,我遇到了以下句子: > 。。。试图从行为参数访问可变状态会给您带来错误的选择。。。如果您不同步对该状态的访问,您将面临数据竞争,因此您的代码将被破坏。。。[1] 如果行为参数确实有副作用。。。[没有]保证在同一个线程中执行同一流管道中“相同”元素上的不同操作。[2] 对于任何给定的元素,可以在库选择的任何时间和线程中执行该操作。[3] 这些句子没有区分顺序流和平行流。因此,我
问题内容: 我对CompletableFuture方法有疑问: 事情是JavaDoc这么说的: 返回一个新的CompletionStage,当此阶段正常完成时,将使用该阶段的结果作为所提供函数的参数来执行该阶段。有关涵盖异常完成的规则,请参见CompletionStage文档。 那线程呢?这将在哪个线程中执行?如果将来由线程池完成怎么办? 问题答案: 文档中指定的策略可以帮助您更好地理解: 对
我有一个关于CompletableFuture方法的问题: 问题是JavaDoc只说了这么一句话: 返回一个新的CompletionStage,当此阶段正常完成时,将以此阶段的结果作为所提供函数的参数执行该CompletionStage。有关例外完成的规则,请参阅CompletionStage文档。 穿线呢?这将在哪个线程中执行?如果未来是由一个线程池来完成的呢?
我需要执行一些任务。有些任务是独立的,有些任务依赖于其他任务的成功执行。独立任务可以并行运行以获得更好的性能。我把这些任务称为服务。列说明哪些服务将以串联方式执行,哪些服务将以并联方式执行。列描述了一组定义的服务所遵循的执行顺序。例如,服务A和B应该并行运行。如果它们已成功执行,则将执行服务C。请注意,服务C并不直接依赖于其先前服务的输出,但它必须在成功执行其先前服务后运行,因为服务C在执行期间需
问题内容: 我的项目有多个使用方法的类。如何告诉Spring Boot Maven插件应将其用作主类? 问题答案: 在pom中添加您的入门班: 要么