目前,我一直在使用FixedThreadPool
细分大型任务。这一切都很好。然而;我现在发现这些任务之一的一部分本身可以细分。我曾经尝试将其他Callables提交给FixedThreadPool
,但是程序挂在Future#get()
上(在代码中标记)
以下程序复制了该问题(我使用了大小为1的FixedThreadPool
使问题更严重)
public class ThreadPoolTest {
static ExecutorService threadPool=Executors.newFixedThreadPool(1);
//method run by inner callable
public void printText(){
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadPoolTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Printed from within thread");
}
//method run by outer callable
public void testThreadPool(){
Callable<Void> printOnAThread=()->{printText(); return null; };
Future<Void> f2=threadPool.submit(printOnAThread);
try {
System.out.println("Called");
f2.get(); //<--hangs here
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ThreadPoolTest.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException("Failed to print in thread", ex);
}
}
public static void testThreadWithinThread(){
ThreadPoolTest t=new ThreadPoolTest();
Callable<Void> testCallable=()->{t.testThreadPool();return null;};
Future<Void> f=threadPool.submit(
testCallable
);
try {
f.get();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ThreadPoolTest.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException("Main thread failed", ex);
}
}
public static void main(String[] args){
testThreadWithinThread();
threadPool.shutdown();
System.out.println("Program exits");
}
}
我期望发生什么
第一个线程被提交。
testThreadWithinThread()
运行testThreadWithinThread()
提交可通话对象(()->{t.testThreadPool();return null;};
)提交的可调用开始“立即”运行
t.testThreadPool();开始运行
testThreadPool();
本身提交一个内部可调用()->{printText(); return null; };
内部可调用无法运行,因为线程池不可用
达到
f.get();
时,外部可调用块将等待。这将释放FixedThreadPool
中的线程内部可调用现在运行完成
f2.get();
不再被阻止,外部可调用运行完成实际发生了什么
如我所料,步骤1-6发生在第7点,当外部可调用对象被阻塞时;由于某种原因,它不释放线程,因此程序挂起。
题
为什么程序此时会挂起?有什么方法可以安全地从可调用对象内部提交可调用对象?
最佳答案
您的线程池包含1个线程。一次只能执行一个可调用/可运行的程序。所有其他提交的任务都排队,直到有线程可以执行它们为止。
增加您的游泳池的大小。
关于java - 在可调用项内将可调用项提交给执行服务会导致程序挂起,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23689137/