一个神奇的错误

2,161 阅读1分钟
Caused by: java.lang.IllegalArgumentException: null
	at java.base/java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1293) ~[na:na]
	......

遇到了这么一个神奇的错误 非法参数异常 ,而且是在创建线程池的时候触发的. 创建线程池的参数如下,可见每个参数都有显式的值.最主要的是在本地运行是正常的,问题出在哪里呢? 先给出结论: 核心线程池大小大于了最大线程池大小.

    private static final ThreadPoolExecutor POOL_EXECUTOR = new ThreadPoolExecutor(3, Runtime.getRuntime().availableProcessors(), 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

让我们点开源码看一下:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();

确实在创建线程池的时候有可能抛出 非法参数异常. 对比下这几条异常条件 corePoolSize < 0 不满足,默认线程池大小为 3 , keepAliveTime < 0 不满足,这里为30秒. 那么剩下的只有 maximumPoolSize <= 0maximumPoolSize < corePoolSize 这两个了. Runtime.getRuntime().availableProcessors()点进去瞅一眼,是个native方法,返回值永远 >=1,那么 maximumPoolSize <= 0自然也不满足了.

  剩下只有maximumPoolSize < corePoolSize 这一条了......这时候我才想起我只有一台一核2G的云主机,开发机有16个框框自然不会报错了.


google一下遇到这个问题的人还挺多的,似乎只能尽量避免这种代码了. 或者将最大线程数目写死? 似乎并没有两全其美的办法.