工作中需要使用Callable执行多线程并拿到返回值,但程序ExecutorService.submit(Callable)没有并发执行,而是以单线程的方式一个个执行,最后发现是由于for循环中使用future.get()导致。
先看问题代码:
public class ThreadTest implements Callable<Long> {
@Override
public Long call() {
long start = System.currentTimeMillis();
try {
// 模拟请求时长
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
return end - start;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ExecutorService pool = Executors.newFixedThreadPool(8);
for (int i = 1; i <= 10; i++) {
// 执行多线程
Future<Long> future = pool.submit(new ThreadTest());
Long timeMillis = future.get();
System.out.println("当前线程耗时: " + timeMillis + " 毫秒");
}
long end = System.currentTimeMillis();
System.out.println("总耗时: " + (end - start) + " 毫秒");
pool.shutdown();
}
}
执行结果:
当前线程耗时: 2008 毫秒
当前线程耗时: 2002 毫秒
当前线程耗时: 2006 毫秒
当前线程耗时: 2000 毫秒
当前线程耗时: 2003 毫秒
当前线程耗时: 2003 毫秒
当前线程耗时: 2002 毫秒
当前线程耗时: 2004 毫秒
当前线程耗时: 2004 毫秒
当前线程耗时: 2004 毫秒
总耗时: 20083 毫秒
可以看到,在for循环过程中使用了future.get()获取异步执行结果,而future.get()方法是等到future对应的线程执行完后获取结果,这就导致了其他代码无法执行,程序单线程执行。
再修改代码:
public class ThreadTest implements Callable<Long> {
@Override
public Long call() {
long start = System.currentTimeMillis();
try {
// 模拟请求时长
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
return end - start;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ExecutorService pool = Executors.newFixedThreadPool(8);
List< Future<Long>> futureList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
// 执行多线程
Future<Long> future = pool.submit(new ThreadTest());
futureList.add(future);
}
for (Future<Long> future : futureList) {
Long timeMillis = future.get();
System.out.println("当前线程耗时: " + timeMillis + " 毫秒");
}
long end = System.currentTimeMillis();
System.out.println("总耗时: " + (end - start) + " 毫秒");
pool.shutdown();
}
}
执行结果:
当前线程耗时: 2010 毫秒
当前线程耗时: 2010 毫秒
当前线程耗时: 2010 毫秒
当前线程耗时: 2010 毫秒
当前线程耗时: 2009 毫秒
当前线程耗时: 2009 毫秒
当前线程耗时: 2009 毫秒
当前线程耗时: 2009 毫秒
当前线程耗时: 2006 毫秒
当前线程耗时: 2006 毫秒
总耗时: 4061 毫秒