先上代码:
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
/**
* @ClassName: AsyncTest
* @Author: Dylan Li
* @Date: 2025/7/25 17:43
*/
public class AsyncTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
AtomicReference<String> str = new AtomicReference<>();
List<CompletableFuture<Void>> futures = new ArrayList<>();
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> new ContextAwareRunnable(
"context()",
() -> {
str.set("Hello World.");
System.out.println("set success");
}
), executor);
futures.add(future);
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
System.out.println("str: " + str.get());
// 关闭线程池
executor.shutdown();
}
static class ContextAwareRunnable implements Runnable {
private final Object context;
private final Runnable task;
public ContextAwareRunnable(Object context, Runnable task) {
this.context = context;
this.task = task;
}
@Override
public void run() {
// 设置上下文(关键步骤)
setContext(context);
try {
task.run(); // 执行传入的业务逻辑
} finally {
removeContext();
}
}
private void setContext(Object context) {
System.out.println("设置上下文:" + context);
}
private void removeContext() {
System.out.println("移除上下文");
}
}
}
猜一下执行结果是什么?
是不是觉得很简单,打印结果肯定是:
设置上下文:context()
set success
移除上下文
str: Hello World.
如果这样想,那么恭喜你……
实际上的执行结果是:
str: null
原因很简单:
Lambda表达式的主体是new ContextAwareRunnable(...) —— 这仅仅是创建了一个Runnable实例,而没有触发它的执行逻辑。因此需要显式调用run()方法,否则ContextAwareRunnable中封装的业务逻辑永远不会执行。
具体来说:
CompletableFuture.runAsync(Runnable task) 要求传入的 task 是一个可执行的 Runnable。在上面的代码中,Lambda 表达式 () -> new ContextAwareRunnable(...) 本身是一个 Runnable,但它的逻辑只是“创建对象”,而非“执行对象的逻辑”。如果不调用 run(),这个 ContextAwareRunnable 实例就只是被创建出来,其内部的业务代码不会被触发。
解决的办法有两个:
-
移除Lambda表达式,代码如下:
CompletableFuture<Void> future = CompletableFuture.runAsync(new ContextAwareRunnable( "context()", () -> { str.set("Hello World."); System.out.println("set success"); } ), executor); futures.add(future); -
调用
run()方法:CompletableFuture<Void> future = CompletableFuture.runAsync(() -> new ContextAwareRunnable( "context()", () -> { str.set("Hello World."); System.out.println("set success"); } ).run(), executor); futures.add(future);
运行代码查看执行结果:
设置上下文:context()
set success
移除上下文
str: Hello World.
除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接
文章评论
再接再厉
Chrome 109.0.0.0中国-江苏-苏州