我有以下类,它在与启动 docker-compose up
的线程相同的线程上运行 FutureTask
。
有没有办法使用 FutureTask
来实现这一点?
我之所以这么问是因为我最终想利用将多个 CompletableFuture
链接在一起的优势。能够指定它们是在与执行线程相同的线程上运行还是在不同的线程上运行。
CompletableFuture
产生以下输出:
public class SameThreadFutureTask {
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println(Thread.currentThread());
Callable<String> action = new Callable<String>() {
public String call() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello "+Thread.currentThread();
}
};
System.out.println("before");
FutureTask<String> ft = new FutureTask<>(action);
ft.run();
System.out.println(ft.get());
System.out.println("After");
}
}
答案 0 :(得分:2)
您可以在没有任何完成的情况下构造一个 new CompletableFuture<>()
,并根据需要链接任意数量的操作。然后,当您知道如何完成它时,调用 complete
以在同一线程中完成或调用 completeAsync
以进行异步完成。
final String main = Thread.currentThread().getName();
for(boolean sameThread: new boolean[] { true, false}) {
System.out.println("will use " + (sameThread? "same thread ("+main+")": "async"));
CompletableFuture<String> initial = new CompletableFuture<>();
CompletableFuture<?> result = initial
.thenApply(s -> {
System.out.println("toUpperCase in " + Thread.currentThread().getName());
return s.toUpperCase();
})
.thenAccept(s -> System.out.println(
"final processing of \"" + s + "\" in " + Thread.currentThread().getName()));
System.out.println("before");
if(sameThread) {
initial.complete("hello " + main);
}
else {
initial.completeAsync(() -> "hello " + Thread.currentThread().getName());
}
System.out.println("after");
result.join();
System.out.println();
}
这演示了两种模式。
will use same thread (main)
before
toUpperCase in main
final processing of "HELLO MAIN" in main
after
will use async
before
after
toUpperCase in ForkJoinPool.commonPool-worker-1
final processing of "HELLO FORKJOINPOOL.COMMONPOOL-WORKER-1" in ForkJoinPool.commonPool-worker-1
请注意,completeAsync
已在 Java 9 中引入。如果您在 Java 8 中需要类似的构造,则必须替换
initial.completeAsync(() -> "hello " + Thread.currentThread().getName());
与
CompletableFuture.runAsync(() -> {
try {
initial.complete("hello " + Thread.currentThread().getName());
} catch(Throwable t) {
initial.completeExceptionally(t);
}
});
答案 1 :(得分:0)
Executor sameThreadExecutor = runnable -> runnable.run();
Runnable myTask = () -> System.out.println("hello "+Thread.currentThread());
CompletableFuture.runAsync(myTask, sameThreadExecutor).get();
能够指定它们是在与执行线程相同的线程上运行还是在不同的线程上运行。
boolean useSameThread = ...;
Executor sameThreadExecutor = runnable -> runnable.run();
Executor forkJoin = ForkJoinPool.commonPool();
Executor preferredExecutor = useSameThread ? sameThreadExecutor : forkJoin;
Runnable hello = () -> System.out.println("hello "+Thread.currentThread());
Runnable helloAgain = () -> System.out.println("hello again " + Thread.currentThread());
Runnable bye = () -> System.out.println("bye " + Thread.currentThread());
CompletableFuture.runAsync(hello, preferredExecutor)
.thenRunAsync(helloAgain, preferredExecutor)
.thenRunAsync(bye, preferredExecutor)
.get();