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");
}
}
What I expected to happen
- First thread is submitted.
testThreadWithinThread()
runs testThreadWithinThread()
submits a Callable (()->{t.testThreadPool();return null;};
)- Submitted callable starts running "immediately"
- t.testThreadPool(); starts running
testThreadPool();
itself submits an inner callable()->{printText(); return null; };
- Inner callable cannot yet run because the thread pool isn't free
f.get();
is reached, the outer callable blocks and waits. This releases the thread within theFixedThreadPool
- The inner callable now runs to completion
f2.get();
is no longer blocked, outer callable runs to completion
What actually happened
Steps 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.
Question
Why does the program hang at this point? Is there any way I can submit callables from within callables safely?