Submitting a callable within a callable to an Executor Service causes the program to hang

StackOverflow https://stackoverflow.com/questions/23689137

  •  23-07-2023
  •  | 
  •  

Domanda

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

  1. First thread is submitted. testThreadWithinThread() runs
  2. testThreadWithinThread() submits a Callable (()->{t.testThreadPool();return null;};)
  3. Submitted callable starts running "immediately"
  4. t.testThreadPool(); starts running
  5. testThreadPool(); itself submits an inner callable ()->{printText(); return null; };
  6. Inner callable cannot yet run because the thread pool isn't free
  7. f.get(); is reached, the outer callable blocks and waits. This releases the thread within the FixedThreadPool
  8. The inner callable now runs to completion
  9. 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?

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top