At present I have been using a FixedThreadPool
to subdivide a large task; this has all been working fine. However; I have now found that part of one of these tasks can itself be subdivided. I used tried to submit further Callables to the FixedThreadPool
but the program hung on the Future#get()
(marked in the code)
The following program replicates the problem (I have used a FixedThreadPool
with size 1 to worsen the problem)
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()
runstestThreadWithinThread()
submits a Callable (()->{t.testThreadPool();return null;};
)testThreadPool();
itself submits an inner callable ()->{printText(); return null; };
f.get();
is reached, the outer callable blocks and waits. This releases the thread within the FixedThreadPool
f2.get();
is no longer blocked, outer callable runs to completionSteps 1-6 happens as I expected however at point 7 when the outer callable is blocked; for some reason it doesn't release the thread and so the program hangs.
Why does the program hang at this point? Is there any way I can submit callables from within callables safely?
Your thread pool contains 1 thread. It can only execute one callable/runnable at a time. All other submitted tasks are queued until a thread is available to execute them.
Increase your pool size.