问题描述
记录下一次代码评审的问题点,发现这个也是自己以前犯过的内容.在使用多线程情况下,查看日志发现似乎还是单线程在跑的效果
问题案例
先看下面的代码
@Slf4j
public class ThreadPoolTest2 {
private static ThreadPoolExecutor testThreadPool = new ThreadPoolExecutor(10, 10, 180L,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new CustomizableThreadFactory("test-pool-"), new ThreadPoolExecutor.CallerRunsPolicy());
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
handlerA();
log.info("耗时->{}ms", System.currentTimeMillis() - startTime);
}
private static void handlerA() {
for (int i = 0; i < 100; i++) {
String param = i + "";
Future<String> resultFuture = testThreadPool.submit(() -> getResult(param));
String result = null;
try {
result = resultFuture.get();
} catch (Exception e) {
e.printStackTrace();
}
log.info("handlerA future get,result->{}", result);
}
}
private static String getResult(String i) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
String result = "result-" + i;
log.info("result->{}", result);
return result;
}
}
查看日志,可以看到是有不同的线程在跑任务,但效果就是单线程的效果.耗时也是单线程情况下的耗时

image.png
问题分析以及解决方案
先看下下面修改后的代码,对比下
private static void handlerB() {
List<Future<String>> futureList = new ArrayList<>();
for (int i = 0; i < 30; i++) {
String param = i + "";
Future<String> resultFuture = testThreadPool.submit(() -> getResult(param));
futureList.add(resultFuture);
}
for (Future<String> resultFuture : futureList) {
String result = null;
try {
result = resultFuture.get();
} catch (Exception e) {
e.printStackTrace();
}
log.info("handlerB future get,result->{}", result);
}
}
先看下效果(可以看到这个才是自己想要的多线程的效果)

image.png
原因分析
其实对比下代码,可以发现,在main线程遍历过程中使用future.get().这个急阻塞main线程等到线程完成任务.这样其实就和单线程是同样的效果了
在优化后的handlerB中,main线程优先使用线程跑任务,最终才使用main从future列表里等待线程任务结束.