JUC并发编程之线程池工作原理及主要参数

概述

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。

优势

1.实现线程的复用,降低频繁创建销毁线程带来的消耗
2.提高线程的可管理性,统一对线程进行监控,分配调优等操作
3.能够控制任务的最大并发数,提高响应的书时间

线程池的主要参数:

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.acc = System.getSecurityManager() == null ?
        null :
    AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

corePoolSize

线程池中的常驻核心线程数

当线程池中的线程数目达到 corePoolSize 后,就会把到达的任务放到缓存队列中去

maximumPoolSize

线程池能够容纳“同时执行的最大线程数”,此值必须大于1

long keepAliveTime

多余的空余线程的存活时间 ,当线程池数量超过 corePoolSize 时,同时当空闲时间达到 keepAliveTime 时,
多余的线程会被销毁,直到只剩下 corePoolSize 个线程为止

TimeUnit unit

keepAliveTime的单位

BlockingQueue workQueue

任务队列,被提交但是未被执行的任务,也就是阻塞队列

ThreadFactory threadFactory

表示生成线程池中工作线程的线程工厂,用于创建线程,一般用默认的即可

RejectedExecutionHandler handler

拒绝策略。表示当队列满了并且工作线程数大于等于线程池的最大线程数 maxmumPoolSize 时,
如何来拒绝任务

线程池工作原理

  • 对应图中 1、2、3、4 四个步骤:
    • 如果核心线程使用数量到了 corePoolSize
    • 那么新的线程先放阻塞队列里,
    • 如果阻塞队列满了,那么就增加核心线程数
    • 此时增加的核心线程数不是指常驻的核心线程,是指临时的核心线程
    • 当增加的临时核心线程数等于 maximumPoolSize 的时候,就不再往线程池中添加新的临时线程
    • 如果此时阻塞队列线程池线程数量都达到阈值并且还源源不断的有新的请求
    • 此时就触发拒绝机制
    • 最后等到阻塞队列为空,线程池中没有线程有要处理的代码段,
    • 此时我们判断临时核心线程的等待时间是否等于 keepAliveTime,如果等于,那就销毁临时核心线程。
    • 最后我们处理完一切事物,就只留下了空空的阻塞队列以及我们线程池的两个常驻核心线程

413ca31c-463a-40ff-bd2e-6df18b707752.png

拒绝策略

  • 以下四个JDK内置的拒绝策略均实现了 RejectedExecutionHandler 接口。
  • AbortPolicy(默认)
    • 直接抛出 RejectedExecutionException 异常。
    • 阻止系统正常运行。
  • CallerRunsPolicy
    • **“调用者运行”**机制,是一种调节机制。
    • 该策略既不会抛弃任务,也不会抛出异常
    • 它会将某些任务回退给调用者,从而降低新任务的流量。
  • DiscardOldestPolicy
    • 抛弃队列中等待最久的任务
    • 然后把当前任务加入到队列中尝试再次提交当前任务
  • DiscardPolicy
    • 直接丢弃该任务。
    • 不处理,不抛异常,如果允许任务丢失的话,这是最好的一种方案。

线程池四种创建方式

Java通过Executors(jdk1.5并发包)提供四种线程池,分别为:

newCachedThreadPool(一池多线程)

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

ExecutorService threadPool = Executors.newCachedThreadPool(); //创建一个可缓存线程池。

newFixedThreadPool (固定线程数)

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

 ExecutorService threadPool = Executors.newFixedThreadPool(5);

newScheduledThreadPool (固定线程数,支持定时任务)

创建一个定长线程池,支持定时及周期性任务执行。

 ScheduledExecutorService es4 = Executors.newScheduledThreadPool(2);

newSingleThreadExecutor(一池一线程)

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

 ExecutorService es1 = Executors.newSingleThreadExecutor();

自定义线程池

通过线程池七大参数的自定义,可以实现线程池的自定义
使用自定义线程池可以根据自己的业务需求,具体定制专属线程池,以更加贴合业务

自定义线程池:

public class CustomThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService threadPool = new ThreadPoolExecutor(2,5
                                                            ,60L, TimeUnit.MILLISECONDS
                                                            , new LinkedBlockingQueue<Runnable>(3)
                                                            , Executors.defaultThreadFactory()
                                                            ,new ThreadPoolExecutor.AbortPolicy());

        try {
            // 此时阻塞队列和线程池最大长度为 8,同时并发超过 8 的话就会造成拒绝
            for (int i = 0; i < 9; i++) {
          //for (int i = 0; i < 8; i++) { // 不会被拒绝
                // 并发 9
                threadPool.submit(() -> {
                    System.out.println(Thread.currentThread().getName() + "线程\t 处理业务!");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值