zoukankan      html  css  js  c++  java
  • 面试题:线程池内线程没有catch处理,抛出异常,线程池会怎么办?

    答案

    当线程池中线程执行任务的时候,任务出现未被捕获的异常的情况下,线程池会将允许该任务的线程从池中移除并销毁,且同时会创建一个新的线程加入到线程池中;可以通过ThreadFactory自定义线程并捕获线程内抛出的异常,也就是说甭管我们是否去捕获和处理线程池中工作线程抛出的异常,这个线程都会从线程池中被移除

    源码

    这道面试题源码在ThreadPoolExecutor#runWorker()方法中

    任务运行是task.run(),进行了try catch处理,catch中将异常直接抛出,所以用户没有进行任何处理时,异常直接抛出。

    (afterExecute方法是为了提供给扩展)

    然后task置为null, 完成任务数加1,主要看后面的finally中调用的processWorkerExit方法

    decrementWorkerCount()将CAS内存中worker存值减一,workers.remove(w)将工作线程移除

    public class ThreadPoolExecutor extends AbstractExecutorService {
        final void runWorker(Worker w) {
            Thread wt = Thread.currentThread();
            Runnable task = w.firstTask;
            w.firstTask = null;
            w.unlock(); // allow interrupts
            boolean completedAbruptly = true;
            try {
                while (task != null || (task = getTask()) != null) {
                    w.lock();
                    // If pool is stopping, ensure thread is interrupted;
                    // if not, ensure thread is not interrupted.  This
                    // requires a recheck in second case to deal with
                    // shutdownNow race while clearing interrupt
                    if ((runStateAtLeast(ctl.get(), STOP) ||
                         (Thread.interrupted() &&
                          runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                        wt.interrupt();
                    try {
                        beforeExecute(wt, task);
                        Throwable thrown = null;
                        try {
                            task.run();
                        } catch (RuntimeException x) {
                            thrown = x; throw x;
                        } catch (Error x) {
                            thrown = x; throw x;
                        } catch (Throwable x) {
                            thrown = x; throw new Error(x);
                        } finally {
                            afterExecute(task, thrown);
                        }
                    } finally {
                        task = null;
                        w.completedTasks++;
                        w.unlock();
                    }
                }
                completedAbruptly = false;
            } finally {
                // 移除线程池
                processWorkerExit(w, completedAbruptly);
            }
        }
    }
    
    protected void afterExecute(Runnable r, Throwable t) { }
    
    public class ThreadPoolExecutor extends AbstractExecutorService {
        private void processWorkerExit(Worker w, boolean completedAbruptly) {
            if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
                // CAS内存中值减一
                decrementWorkerCount();
    
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                completedTaskCount += w.completedTasks;
                // 移除线程池
                workers.remove(w);
            } finally {
                mainLock.unlock();
            }
    
            tryTerminate();
    
            int c = ctl.get();
            if (runStateLessThan(c, STOP)) {
                if (!completedAbruptly) {
                    int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                    if (min == 0 && ! workQueue.isEmpty())
                        min = 1;
                    if (workerCountOf(c) >= min)
                        return; // replacement not needed
                }
                addWorker(null, false);
            }
        }
    }
    

    https://blog.csdn.net/luxiaoruo/article/details/106637384

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    SQL Server外键关系是强制约束,外键值也可以是空(NULL)
    SQL怎么实现SLEEP功能(等待时间) -(转载)
    Why use async requests instead of using a larger threadpool?(转载)
    c# &与&& 和 |与||的区别(转载)
    SQL Server分区表,能否按照多个列作为分区函数的分区依据(转载)
    怎样避免C#中将小数转换为字符串时出现科学记数法
    锁不住的查询(转载)
    JSON中如何转义字符串中的双引号(转载)
    StreamWriter结合UTF-8编码使用不当,会造成BOM(Byte Order Mark )问题生成乱码(转载)
    HttpWebRequest的timeout和ReadWriteTimeout(转载)
  • 原文地址:https://www.cnblogs.com/caozibiao/p/14343414.html
Copyright © 2011-2022 走看看