0
点赞
收藏
分享

微信扫一扫

java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part7~整起(打手集团【线程池】)

特此感谢,低并发编程老师的公众号里面讲的线程池一节,受益匪浅,才有了自己整理的笔记
在这里插入图片描述
一步一步拆解框图,如下:

  • 如果我自己来设计这个工具类的话(出题人给定了一个接口:public interface Executor{public void execute(Runnable r)};)。那思路就是,我写一个类实现出题人给的接口,类里面重写接口里面的方法,方法体就是最初的想要异步执行的程序,new Thread®.start();相当于不管是伙伴A,伙伴B…都来调用我这个子类中的重写过的方法就行,不用你们自己去new Thread®.start();
public ExecutorVersion01 implements Executor{
	public void execute(Runnable r){
		new Thread(r).start();
	}
}
  • 方便了一点点,但是,要是一亿个人都调这个子类中的方法去想要异步执行,他其实也是创建了一亿个线程呀,这么多线程肯定不合适吧,你一个饭馆会招聘这么多服务员嘛,肯定不会呀,肯定要共用起来好一点呀。好,那先实现一下控制一下线程的数量
    在这里插入图片描述
  • 一个Worker貌似有点少(要是tasks队列满了怎么办,相当于客人来的很多你一个服务员手脚再麻利也忙不过来呀)。好,那先把Worker线程的数量增加一下
    • 具体数量让使用者决定。调用时再传入(叫做核心线程数corePoolSize)
      在这里插入图片描述
      至此,设计思路大体完成,打眼一看,还有几个缺陷:
  • 假设当提交任务的数量突增时,工作线程Worker和任务队列Tasks都被占满了,就只能走拒绝策略,其实就是被丢弃掉,这还不是赶走客人嘛
    在这里插入图片描述
    在这里插入图片描述

我们可以发明一个新属性,叫最大线程数maximumPoolSize.当核心线程数和队列都满了时,新提交的任务仍然可以通过创建新的工作线程(叫做非核心线程),直到工作线程数达到maximumPoolSize为止(这样就可以缓解一时的QPS高峰期了,我也不用无脑去设置过大的核心线程数了)

  • 开始时当workCount < corePoolSize时,通过创建新的Worker(此时虽然前几个线程本质上和之前的Worker一样,但是此时叫做核心线程)来执行任务
  • 当workCount >= corePoolSize时,停止创建新线程,把任务直接丢到任务队列中
  • 又当任务队列一满时,workCount < maximumPoolSize时,不再直接走拒绝策略(满了就丢那种),而是创建非核心线程,直到workCount = maximumPoolSize再满了的话再走拒绝策略
    在这里插入图片描述

在重新回顾一下,线程池的定义
线程池(程序运行的本质就是(进程和线程)占用系统的资源,所以为了优化资源的使用,才有了池化技术),在池子里创建线程。
在这里插入图片描述
接下来就是:三大方法+7大参数+4种拒绝策略

  • 三大方法**(Executors这个工具类中的三大方法,但是阿里巴巴开发手册上说不允许用Executors去创建线程池而是通过ThreadPoolExecutor的方式):三大方法的底层都是在方法中return new ThreadPoolExecutor(…)来实现开启了线程池**
    在这里插入图片描述
    框中的三个方法,如下:
    在这里插入图片描述
    调用Executors的三大方法返回或者说创建一个线程池的代码如下:
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Executors.newFixedThreadPool(5);//创建一个有固定数目线程的线程池
Executors.newCachedThreadPool();//创建一个可伸缩的,遇强则强遇弱则弱的线程池

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这三个方法都是Executors接口的,咱们再看看这个接口:顶层接口Executors详解(可以把这个类看作是一个工具类,它里面有三大方法可以用来创建线程池,)
在这里插入图片描述
有几个注意点:
在这里插入图片描述

在这里插入图片描述
另外,这个Executors接口中的三大方法底层都是在方法中return new ThreadPoolExecutor(…)来实现开启了线程池
在这里插入图片描述
内部有一个this进行调用,咱顺着this往下找
在这里插入图片描述
在这里插入图片描述
那咱们再继续顺着看看这七个参数:

public ExecutorByHu(
        int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler) 
{
    ... // 省略一些参数校验
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

在这里插入图片描述
下来一个一个具体看:

  • int corePoolSize:核心线程数(核心线程池大小)
    在这里插入图片描述
  • int maximumPoolSize:最大线程池大小
    在这里插入图片描述
  • long keepAliveTime:非核心线程的空闲时间
    在这里插入图片描述
  • TimeUnit util:空闲时间的单位(超时单位)
  • BlockingQueue workQueue:任务队列(线程安全的阻塞队列)
    在这里插入图片描述
  • ThreadFactory threadFactory:线程工厂,用来创建线程的,一般不用动(Executors.defaultThreadFactory();)
    在这里插入图片描述
  • RejectedExecutionHandler handler:拒绝策略(有四种拒绝策略,各有各的拒绝特点)

拒绝策略(有四种拒绝策略,各有各的拒绝特点);相当于银行那种,有五个柜台,然后假设还有一个候客区共有5个座位。然后假如人很多时,柜台已经有五个人在办业务了并且候客区也坐满了五个人,那么如果第十一个来了,就得用拒绝策略把第十一个人拒绝了
在这里插入图片描述

  1. 第一种拒绝策略是:(在线程池这里体现出来就是如果第11个人来了就不处理并抛出异常)
    在这里插入图片描述
  2. List item
  3. 队列满了后,第11个人就会被默默抛弃不会被处理(执行),也不会抛出啥异常
    在这里插入图片描述
  4. List item

下来再看看几个赠送的礼品:
在这里插入图片描述
使用线程池时:
在这里插入图片描述
ok,拜拜~

举报

相关推荐

多线程与高并发--------线程池

0 条评论