ThreadPoolExecutor使用一坑

2019-07-08

先来看一段代码

public class ThreadMain {

    private static class SimpleThreadFactory implements ThreadFactory {
        private static final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        public SimpleThreadFactory() {
            namePrefix = "simple-pool-thread-";
        }

        public Thread newThread(Runnable r) {
            int i = threadNumber.getAndIncrement();
            return new Thread(namePrefix + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        ExecutorService executorService = new ThreadPoolExecutor(1, 1, 60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10), new SimpleThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

        executorService.submit(() -> {
            try {
                System.out.println("worker done");
            } catch (Throwable e) {
                e.printStackTrace();
            } finally {
                countDownLatch.countDown();
            }
        });

        countDownLatch.await();

        System.out.println("main done");

        executorService.shutdown();
    }
}

很简单的一段代码,main方法中用ThreadPoolExecutor定义了一个线程池,用CountDownLatch做同步,主线程在工作线程打印出worker done后,打印main done并退出。实际运行,发现控制台没有任何输出。问题出在哪呢?

经过分析可知,工作线程没有执行任务,countDownLatch没有计数,于是主线程阻塞了,可为什么任务不执行呢?

直接揭晓结果,看这段代码:

public Thread newThread(Runnable r) {
    int i = threadNumber.getAndIncrement();
    return new Thread(namePrefix + i);
}

SimpleThreadFactory类实现ThreadFactory,用于自定义自己的线程工厂,需要实现newThread方法,其他有个Runnable类型的参数r,上面这段代码没有用到这个参数,被初始化的线程中待执行的任务为空,看下面这段Thread类中的代码:

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

target对应上面newThread方法中的参数r,那就明白了:线程池中初始化了一个线程,但这个线程没有任务,那任务自然不能被执行,打印任务不能完成,修改后的代码如下:

public Thread newThread(Runnable r) {
    int i = threadNumber.getAndIncrement();
    return new Thread(r, namePrefix + i);
}

之后程序可以正常运行退出