【发布时间】:2015-01-13 18:44:58
【问题描述】:
在为ExecutorService invokeAll 编写骨架程序时,我遇到了一个有趣的场景,它似乎造成了死锁。无法弄清楚为什么会这样。
这是实例化3个任务并调用invokeAll()的程序
int poolSize = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
Set<Callable<Object>> tasksSet = new HashSet<>();
tasksSet.add(new Task1());
tasksSet.add(new Task2());
tasksSet.add(new Task3());
List<Future<Object>> resultSet = pool.invokeAll(tasksSet);
for (Future<Object> future : resultSet) {
Object result;
try {
result = future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (TimeoutException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
pool.shutdown();
还有Task1代码:
public class Task1 implements Callable<Object> {
@Override
public Object call() throws Exception {
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
val += i;
}
return "Sucessfull Task1 object...";
}
}
Task2 和 Task3 代码也相同,除了这两个类在循环检查中使用 Integer.MAX_VALUE。
当我运行这个程序时,它永远卡住了,有趣的是,其他两个任务也没有运行。我的机器是8核处理器。有什么想法为什么会出现这种行为?
如果我将 Long.MAX_VALUE 更改为 Integer.MAX_VALUE,一切正常。
另一个有趣的观察是:
如果submit() 单独调用这些任务,而不是调用invokeAll(),除Task1(具有Long.MAX_VALUE)之外的另外两个任务按时完成。
【问题讨论】:
-
您有没有机会为您的程序获得线程转储?这将是确定是否确实存在死锁的最佳方法。
-
它总是可重现的,因此获取线程转储可能不是问题。但我在这里苦苦挣扎的是,在多核机器上,任务处理不应该是并发的吗?
标签: java-7 executorservice java.util.concurrent