目前,我一直在使用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/

10-12 20:33