Java并发编程---线程池原理分析

最近看了线程池相关,进行相关记录;
线程池工作流程
在这里插入图片描述

一.首先,线程池的优点如下:
1)控制线程数量;
2)减低频繁创造和销毁线程;
3)对于任务的响应速度更快;
二.Executors详解
在入门的时候,可以了解到通过Executors进行创建线程池

     // 只有一个核心线程的线程池
      ExecutorService executorService = Executors.newSingleThreadExecutor();

      // 固定线程数的线程池
      ExecutorService executorService1 = Executors.newFixedThreadPool(3);

      // 伸缩性,60s回收
      ExecutorService executorService2 = Executors.newCachedThreadPool();

这三者,他们的底层都是如下实现如下方法:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
    
    
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

1、corePoolSize(线程池基本大小):当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数大于或等于corePoolSize时,(除了利用提交新任务来创建和启动线程(按需构造),也可以通过 prestartCoreThread() 或 prestartAllCoreThreads() 方法来提前启动线程池中的基本线程。)

2、maximumPoolSize(线程池最大大小):线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可忽略该参数。

3、keepAliveTime(线程存活保持时间)当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。

4、workQueue(任务队列):用于传输和保存等待执行任务的阻塞队列。

5、threadFactory(线程工厂):用于创建新线程。threadFactory创建的线程也是采用new Thread()方式,threadFactory创建的线程名都具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号)。

5、handler(线程饱和策略):当线程池和队列都满了,再加入线程会执行此策略。
那么,在工作中,我们一般选择怎么创建线程池呢?
先公布答案,以上三种都不采纳; 因为阿里巴巴开发手册告诉我们,不推荐使用这三个创建,如果要使用,需要我们自己实现TreadPoolExecutor。
为什么不可以使用上面三个创建线程池呢?
1,首先newCachedThreadPool的源码中

    public static ExecutorService newCachedThreadPool() {
    
    
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

在这里插入图片描述
很显然,它的maximumPoolSize参数的最大值为Integer.MAX_VALUE,即大约为21亿;如果数据量大的话,大量线程创建,就会造成OOM;
2.newSingleThreadExecutor和newFixedThreadPool中,则是

   public static ExecutorService newSingleThreadExecutor() {
    
    
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

在这里插入图片描述

在这里插入图片描述
它们允许请求队列的长度为Integer.MAX_VALUES,会堆积大量的请求,造成OOM;

三.对于execute()和submit()方法
1.execute(),执行一个任务,没有返回值;而submit()有返回值
2.execute()执行出现异常,可以抛出;而submit()不会抛出异常
3.exectue()只能接受Runnable接口;而submit()可以Callable或者Runnable;

借鉴相关博客:
http://ifeve.com/java-threadpool/
https://blog.csdn.net/ityouknow/article/details/82393099

Guess you like

Origin blog.csdn.net/qq_35529931/article/details/113475700