线程池执行异常不打印日志

public class ThreadPoolTest {



    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(500),
            new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r);
                    thread.setName("submit-execute-test");
                    return thread;
                }


            }
    );

    private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS");

    public static void main(String[] args) {
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            int j = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(2 + random.nextInt(5));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (j % 2 != 0) {
                        throw new RuntimeException("线程错误");
                    }
                    LinkedBlockingQueue<Runnable> queue = (LinkedBlockingQueue) executor.getQueue();
                    System.out.println(formatter.format(LocalDateTime.now()) + "::" + Thread.currentThread().getName() + "::" +
                            "核心线程数 :" + executor.getCorePoolSize() +
                            "::最大线程数 :" + executor.getMaximumPoolSize() +
                            "::活动线程数 :" + executor.getActiveCount() +
                            "::任务完成数" + executor.getCompletedTaskCount() +
                            "::队列使用 :" + queue.size() + "::队列未使用 :" + queue.remainingCapacity() + "::队列总共大小 :" + (queue.size() + queue.remainingCapacity()));


                }
            });

        }
    }
}

从打印中可以看到当execute提交runable的时候异常会输出。

2、我们将execute 换成submit ,其他都不变,再次查看运行情况

可以看出除了我们在代码里面输出内容并未抛出异常。

public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

newTaskFor 方法是创建FutureTask 对象,那么具体不抛异常应该就在FutureTask的run方法了。

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

FutureTask 的run方法,在run方法中对Throwable 异常进行捕获,错误的时候将异常设置到返回结果。执行正常结束,将返回结果set到结果中

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    //设置异常到返回结构中
                    setException(ex);
                }
                //执行正确结束设置返回结果
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
经验分享 程序员 微信小程序 职场和发展