原创

自问自答:关于线程池一些疑惑

老规矩,先让我唠叨两句 :joy:

在我接触的项目中(:sob:),使用多线程的场景少之又少,更别提什么线程池了。但是在面试中这东西问的太多了,所以为了不被再次虐到,就总结下,跟别人吹牛逼去:grin:

不懂线程池的几个参数的可以查看:一文读懂Executors.newFixedThreadPool(int)

当线程corePoolSize大于maximumPoolSize会出现什么情况

会抛出IllegalArgumentException异常,这个我们可以通过源码得知,但是在实际使用中也是这样的。源码如下

JAVA线程池核心数满了后什么时候开始创建新的线程

唠叨开始,不想看可以进入正文

这个我在准备面试前自己也没搞懂,因为他们都没过我,所以即便我知道我对这问题不理解,但是也没亲自去弄明白,(music)直到后来有一天(,你和它走在一起,我才发现,原来爱情,不是真心就可以。。。点我去听)。阿里小姐姐问我,你对线程池有什么理解,能讲讲吗?然后我就哗啦哗啦把我知道的和用的,而且把上次因为线程池问题线程产生的OOM问题我也给她讲了,然后好像她还听满意。但是她又开始问了,就是上面的这个问题,我就一脸懵逼。。早知如此何必不弄明白呢。。。

当任务来的时候,判断是否有线程,没有就创建,当大于核心线程池后,放到任务队列,队列满了后创建新的线程执行,直到线程数等于最大线程数,当任务执行完后,线程会等待设置的时长后销毁,包括核心线程,都会销毁,直到active的线程数是0。
我们前面提到任务队列,因为任务队列又有多种(参考:一文读懂Executors.newFixedThreadPool(int) ),因此这个问题只适合有界队列!,下面我们来验证这个结论。

我们设置任务队列大小为10,线程池大小为5,最大线程数为10,利用 Thread.sleep(1000*60)让线程处于任务状态

import java.util.concurrent.*;

public class ThreadPoolTest {

    public static void main(String[] args) {
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10);
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5,10,2, TimeUnit.SECONDS,workQueue);
        for (int i = 0; i < 20; i++) {
            threadPool.submit(() -> {
                try {
                    Thread.sleep(1000*60);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

            String name = Thread.currentThread().getName()+"-"+i;
            System.out.println(name+":正在执行任务线程数:"+threadPool.getActiveCount());
            System.out.println(name+":线程池的大小:"+threadPool.getCorePoolSize());
            System.out.println(name+":最大线程池大小:"+threadPool.getMaximumPoolSize());
            System.out.println(name+":正在执行任务数:"+threadPool.getTaskCount());//这个值是近似的,因为实际开发中,这个任务可能随时结束。
            System.out.println("--------------------------------");
        }
        threadPool.shutdown();
    }

}

控制台输出:

main-0:正在执行任务线程数:1
main-0:线程池的大小:5
main-0:最大线程池大小:10
main-0:正在执行任务数:1
--------------------------------
main-1:正在执行任务线程数:2
main-1:线程池的大小:5
main-1:最大线程池大小:10
main-1:正在执行任务数:2
--------------------------------
main-2:正在执行任务线程数:3
main-2:线程池的大小:5
main-2:最大线程池大小:10
main-2:正在执行任务数:3
--------------------------------
main-3:正在执行任务线程数:4
main-3:线程池的大小:5
main-3:最大线程池大小:10
main-3:正在执行任务数:4
--------------------------------
main-4:正在执行任务线程数:5
main-4:线程池的大小:5
main-4:最大线程池大小:10
main-4:正在执行任务数:5
--------------------------------
main-5:正在执行任务线程数:5
main-5:线程池的大小:5
main-5:最大线程池大小:10
main-5:正在执行任务数:6
--------------------------------
main-6:正在执行任务线程数:5
main-6:线程池的大小:5
main-6:最大线程池大小:10
main-6:正在执行任务数:7
--------------------------------
main-7:正在执行任务线程数:5
main-7:线程池的大小:5
main-7:最大线程池大小:10
main-7:正在执行任务数:8
--------------------------------
main-8:正在执行任务线程数:5
main-8:线程池的大小:5
main-8:最大线程池大小:10
main-8:正在执行任务数:9
--------------------------------
main-9:正在执行任务线程数:5
main-9:线程池的大小:5
main-9:最大线程池大小:10
main-9:正在执行任务数:10
--------------------------------
main-10:正在执行任务线程数:5
main-10:线程池的大小:5
main-10:最大线程池大小:10
main-10:正在执行任务数:11
--------------------------------
main-11:正在执行任务线程数:5
main-11:线程池的大小:5
main-11:最大线程池大小:10
main-11:正在执行任务数:12
--------------------------------
main-12:正在执行任务线程数:5
main-12:线程池的大小:5
main-12:最大线程池大小:10
main-12:正在执行任务数:13
--------------------------------
main-13:正在执行任务线程数:5
main-13:线程池的大小:5
main-13:最大线程池大小:10
main-13:正在执行任务数:14
--------------------------------
main-14:正在执行任务线程数:5
main-14:线程池的大小:5
main-14:最大线程池大小:10
main-14:正在执行任务数:15
--------------------------------
我们观察到从这里开始执行任务的线程数增加了,此时任务数为15corePoolSize+任务队列大小)的临界值
main-15:正在执行任务线程数:6
main-15:线程池的大小:5
main-15:最大线程池大小:10
main-15:正在执行任务数:16
--------------------------------
main-16:正在执行任务线程数:7
main-16:线程池的大小:5
main-16:最大线程池大小:10
main-16:正在执行任务数:17
--------------------------------
main-17:正在执行任务线程数:8
main-17:线程池的大小:5
main-17:最大线程池大小:10
main-17:正在执行任务数:18
--------------------------------
main-18:正在执行任务线程数:9
main-18:线程池的大小:5
main-18:最大线程池大小:10
main-18:正在执行任务数:19
--------------------------------
main-19:正在执行任务线程数:10
main-19:线程池的大小:5
main-19:最大线程池大小:10
main-19:正在执行任务数:20
--------------------------------

:revolving_hearts: 我们观察到从main-15开始执行任务的线程数增加了,此时任务数为15(corePoolSize+任务队列大小)的临界值。

还有什么问题,以后补充。。
每天学习一点点,进步不会一点点:anger:

正文到此结束(点击广告是对作者最大的支持)