ThreadPoolExecutor在关闭之前没有完全执行线程

时间:2015-05-19 17:32:44

标签: java multithreading

当我运行时:

import java.util.concurrent.*;

public class Foo {

    static public ExecutorService pool =
            new ThreadPoolExecutor(
                    50, 200, 15, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(),
                    ExLogThread.factory);

    public static void main(String args[]) {
        try {
            pool.execute(Foo::startApp);
            pool.shutdown();
            System.exit(0);
        } catch (Exception ex) {
            for (StackTraceElement elem : ex.getStackTrace())
                System.out.println(elem);
            System.exit(-1);
        }
    }

    static void startApp() {
        throw new RuntimeException();
    }

}

final class ExLogThread extends Thread {

    public static final ThreadFactory factory =
            ExLogThreadFactory.instance;
    private final StackTraceElement[] predecessor;
    private final Runnable r;

    public ExLogThread(Runnable r) {
        super();
        predecessor = Thread.currentThread().getStackTrace();
        this.r = r;
    }

    @Override
    public void run() {
        try {
            r.run();
        } catch (Exception ex) {
            log(ex, predecessor);
            System.exit(-1);
        }
    }

    private static class ExLogThreadFactory
            implements ThreadFactory {

        static public ExLogThreadFactory instance =
                new ExLogThreadFactory();

        @Override
        public Thread newThread(Runnable r) {
            return new ExLogThread(r);
        }

        private ExLogThreadFactory() {}

    }

    private static void log(Exception ex, StackTraceElement[] predecessor) {
        // for example's sake
        for (StackTraceElement elem : ex.getStackTrace())
            System.out.println(elem);
        for (int i = 1; i < predecessor.length; i++)
            System.out.println(predecessor[i]);
    }

}

它以0的代码退出。发生了什么?我以为ThreadPoolExexcutor在关闭之前等待排队的任务运行。如果是这样,则应该以-1的代码退出。

如果我没有将线程的创建委托给创建线程子类的工厂,那么在主线程以代码0退出之前,我会收到错误通知。

我猜我在创建Thread的子类时遇到了问题,但我不知道在哪里。帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

致电pool#awaitTermination

后致电pool#shutdown

来自shutdown's javadoc

  

此方法不会等待先前提交的任务完成   执行。使用awaitTermination来做到这一点。

答案 1 :(得分:1)

您对System.exit(0)的来电将终止正在运行的ExecutorService

shutdown()的调用是无阻塞的;它只是向执行程序服务发出信号,表示不再提交任何任务,因此可以在已提交的任务完成时清理资源。因为它没有阻止,所以立即调用System.exit(0),中止提交的任务。

如果您希望线程等到提交到ExecutorService的所有任务都已完成,请致电awaitTermination(),,表明您愿意等多久。