JUC- 线程池

什么是线程池

问题: 在程序中频繁的进行连接-中断-连接会浪费大量资源。

解决: 将这些连接资源,放在一个池子当中。通过复用来提升性能

具体: 先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。

优点

  1. 降低资源消耗
  2. 提高响应
  3. 方便管理

使用

三大方法

public class PoolTest {
    public static void main(String[] args) {
        Executors.newCachedThreadPool();//可伸缩的,最大21亿
        Executors.newSingleThreadExecutor();//单个线程
        Executors.newFixedThreadPool(5);//创建固定大小的线程池
    }
}
复制代码

七大参数

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
复制代码

由此我们可以看出这三个方法的本质都是调用ThreadPoolExecutor来执行的。
而我们点进ThreadPoolExecutor的源码一看

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
复制代码

发现调用了一个this,出于好奇我们再看看这个this是什么

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();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
复制代码

由此我们可以得知其本质是ThreadPoolExecutor的构造函数,其中有七大参数

int corePoolSize, //核心线程数
int maximumPoolSize, //最大线程数
long keepAliveTime, // 每隔多久检查线程是否健康
TimeUnit unit, // 检查的时间单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler //拒绝策略
复制代码
  1. corePoolSize是我们平时线程池最多开启线程的数量
  2. 当超过该数量时就存入阻塞队列workQueue进行等待
  3. 如果阻塞队列workQueue放不下了,我们就多开启线程使其达到maximumPoolSize个。
  4. 如果还不够则根据拒绝策略handler对超过的线程进行拒绝,

四种拒绝策略

  1. ThreadPoolExecutor.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。
  2. ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务(和最早的竞争,不抛异常
  4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务,哪来的回哪去

如何定义最大线程数maximumPoolSize

  1. CPU密集型:有几个cpu就设置几个,cpu利用率最大
  2. IO密集型: 判断有大量IO的线程有几个,只要大于这个数量即可。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享