背景
最近遇到了一个业务,需要做个并发处理 没想到遇到了很大的乌龙 还好没上线 最后改为下游提供批量接口
案例一
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = newFixedThreadPool(5);
ArrayList<Integer> objects = new ArrayList<>();
ArrayList<Callable<Integer>> threadList = new ArrayList<>();
AtomicInteger batchNum = new AtomicInteger(1);
for (int i = 0; i < 10; i++) {
// 幂等id
Future<Integer> future = null;
try {
System.out.println("提交一个"+batchNum.get()+"线程");
future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
System.out.println("第"+batchNum.get()+"次执行");
System.out.println("线程执行:"+ batchNum.getAndIncrement());
return batchNum.get() ;
}
});
if (future != null) {
objects.add(future.get());
}
} catch (Exception e) {
LoggerUtil.warn(LOGGER, e, "id:{0},exception:{1}", batchNum.get(), e.getMessage());
}
}
// List<Future<Integer>> futures = executorService.invokeAll(threadList);
executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("提交一个"+batchNum.get()+"线程");
Thread.sleep(10000);
System.out.println("第"+batchNum.get()+"次执行");
System.out.println("线程执行:"+ batchNum.getAndIncrement());
return batchNum.get() ;
}
});
executorService.shutdown();
System.out.println(executorService.isShutdown());
// executorService.shutdown();
System.out.println("aaaaa");
}
错误1
预期 提交10个线程 并发执行
循环创建线程 会阻塞代码 会等到线程执行完 才会执行下一个线程
错误2
预期 executorService.shutdown(); 会阻塞等待线程执行完 才会关闭线程池 在执行后面代码
实际 直接关闭线程池 不阻塞代码 但线程还是会继续执行,业务不统一
贴下运行效果
网上查了资料后 修改后代码
修复案例
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = newFixedThreadPool(5);
ArrayList<Callable<Integer>> threadList = new ArrayList<>();
AtomicInteger batchNum = new AtomicInteger(1);
for (int i = 0; i < 10; i++) {
// 幂等id
try {
System.out.println("提交一个"+batchNum.get()+"线程");
threadList.add(() ->{
Thread.sleep(2000);
System.out.println("线程执行:"+ batchNum.getAndIncrement());
return batchNum.get() ;
});
} catch (Exception e) {
LoggerUtil.warn(LOGGER, e, "id:{0},exception:{1}", batchNum.get(), e.getMessage());
}
}
List<Future<Integer>> futures = executorService.invokeAll(threadList);
executorService.shutdown();
System.out.println(executorService.isShutdown());
System.out.println("aaaaa");
}
这样和预期结果 比较符合了 但是线程池创建不太友好 这里贴下
<bean
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10"/>
<property name="keepAliveSeconds" value="60"/>
<property name="maxPoolSize" value="15"/>
<!-- 线程池缓冲队列中长度,这里设置为5,按照FIFO规则 -->
<property name="queueCapacity" value="500"/>
<property name="threadNamePrefix" value="asynExecutor"/>
</bean>
如有不足 欢迎指正