让调用者自己干活的特殊线程池
1. 相关背景
单元测试时, 我们的某些业务代码可能是在线程池中运行的,可能会出现各种不一致的情况。
这时候可以hack一下, 创建一个调用者直接执行的线程池,避免干扰;
2. 实现代码
import java.util.concurrent.*;// 让调用者自己执行的线程池
public class CallerRunsExecutor extends ThreadPoolExecutor {public CallerRunsExecutor() {super(0, 1, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));}@Overridepublic void execute(Runnable command) {command.run();}// 获取实例public static CallerRunsExecutor getInstance() {return new CallerRunsExecutor();}
}
3. SpringBoot配置实例
在 SpringBoot 对应的 @Configuration
配置中对Bean进行hack:
// 是否是集成测试环境public static final AtomicBoolean itEnv = new AtomicBoolean(false);@Beanpublic ExecutorService longtimeExecutor() {if (itEnv.get()){// 是否是集成测试环境return CallerRunsExecutor.getInstance();}return new ThreadPoolExecutor(1, 10,60L,TimeUnit.SECONDS,new LinkedBlockingQueue<>(2),new CustomizableThreadFactory("xxxExecutor-"));}
然后在基础的单元测试代码中对相应的值进行设置:
@BeforeClasspublic static void initEnv() {// ...// 是否是集成测试环境XXXXConfiguration.itEnv.set(true);}
4. 测试代码
这里通过一个main方法来测试:
public static void main(String[] args) {// 测试 execute 方法;CallerRunsExecutor.getInstance().execute(new Runnable() {@Overridepublic void run() {System.out.println("execute run in " + Thread.currentThread().getName());}});// 测试 submit 方法;Future<?> future = CallerRunsExecutor.getInstance().submit(new Runnable() {@Overridepublic void run() {System.out.println("submit run in " + Thread.currentThread().getName());}});try {Object result = future.get();} catch (Exception e) {e.printStackTrace();}// 正常输出System.out.println("main in " + Thread.currentThread().getName());}
5. 测试结果
测试结果为:
execute run in main
submit run in main
main in main
结果符合预期。
应用到我们的单元测试环境之中,也是符合预期的。
6. 相关问题
- 1、注意限制使用环境, 不要影响生产;
- 2、需要演示多个线程交互执行的某些代码可能会有问题;
日期: 2024年05月15日
作者: 铁锚 at CSDN