当前位置: 首页 > news >正文

多线程——线程池

课程:
在这里插入图片描述

什么是线程池

可以自己实现这个功能,自己写一个线程池
jdk也给提供了线程池
在这里插入图片描述

为什么要有线程池

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

Executor框架

在这里插入图片描述
在这里插入图片描述
任务:就是代码
执行:谁去执行这个代码,之前是Thread执行的,
在这里插入图片描述
thread:
在这里插入图片描述
Executor:
在这里插入图片描述

Executor框架的接口与类结构

什么是juc

传统的java实现线程:
Thread类和Runnable都是java,lang包下的。

jdk从1.5开始,提供了新的三个包,简称为juc,这三个包用来实现并发编程的:
在这里插入图片描述

Executor框架结构:

在这里插入图片描述

实现:

在这里插入图片描述

Executors

像是Arrays:一个接口名+s, 是表示jdk里的对于这个接口类型的一个工具类的包装。

上面创建的时候要传很多参数,所以用这个工具类,不用去传参数直接获取想要的线程池,这种里面参数是不能修改的了,上面的可以修改我们想要的参数
在这里插入图片描述
源码:
在这里插入图片描述
接收的接口:
在这里插入图片描述

线程池的七大参数解读

核心线程数

在这里插入图片描述

允许核心线程数超时allowCoreThreadTimeOut():

在这里插入图片描述
值默认是false, 永远都在池中不会被销毁
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果想让核心线程数在没有任务的时候也把他销毁:
设置为true:
在这里插入图片描述
这时候这个方法没有返回值,无法打印:
在这里插入图片描述

需要提交任务之后,才有线程

当我们提交任务之后,线程池中才会创建一个线程
在这里插入图片描述

想创建后立马创建线程:

在这里插入图片描述

阻塞队列

先暂时理解下,后面详细讲
先理解一个容器,可以往里面放数据,从里面取数据。先做个粗略的理解。
在这里插入图片描述
设置容量为自定义,如下设置为5:
在这里插入图片描述

最大线程数

池中最多能有多少个线程
在这里插入图片描述
不停提交任务,核心线程数用完,继续提交就存到队列里,队列满了再提交,就会再启动线程,如下设置了10个,那么就可以再临时创建10-5(核心)=5个线程
在这里插入图片描述

空闲线程超时时间和时间单位

上面那个如果设置了,核心线程也会被清理。
不设置就是清理非核心线程。
在这里插入图片描述
单位:设置的
在这里插入图片描述

如下:
就是5个非核心线程如果是空闲状态,空闲了15s,那么这5个非核心线程就会被销毁。
在这里插入图片描述

线程工厂

在这里插入图片描述
如下:
在这里插入图片描述
看源码:
在这里插入图片描述
线程工厂是一个接口:
有一个抽象方法:
存一个runnable, 给他创建一个线程返回
在这里插入图片描述
接口默认在jdk并发包里有两个实现:还有一个子实现:
找包对的,其他都不是并发包下的
在这里插入图片描述
默认用这两个实现就可以了:
这里用的工具类里的方法获取:
在这里插入图片描述
点进去看源码:
他就是给我们创建了一个默认的线程工厂的实现:
在这里插入图片描述
使用获取子类的线程工厂:
在这里插入图片描述

default线程工厂实现

在这里插入图片描述
点进去:
实现了接口,覆盖了newThread方法:
在这里插入图片描述
源码解读:
597:线程池个数编号,原子类后面会将
598:线程组
599:线程的编号,也是原子类,初始值是1
600:线程的名字的前缀
构造方法:
把线程组进行一个初始化,给线程名字前缀初始化
在这里插入图片描述
创建线程:
new一个线程:
参数:线程组,runnable,线程名字前缀拼上编号,栈的大小

线程如果是守护线程,改成非守护线程
线程优先级如果不是5,把优先级改成5
返回new的这个线程。
在这里插入图片描述

子类线程工厂实现

在这里插入图片描述
继承了default,default里有的东西相当于继承过来了。
首先继承了构造方法,super一下,把default里构造方法东西继承过来。
然后自己做了一些判断
在这里插入图片描述
new线程时:
用了父类的,实现的时候做了一些安全的检查
在这里插入图片描述
所以这个线程工厂上面有一些说明:
和当前线程有一些相同权限的线程工厂
在这里插入图片描述

自定义线程工厂

在这里插入图片描述
使用:
在这里插入图片描述

拒绝策略

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

拒绝策略参数源码:

参数位置:
在这里插入图片描述
拒绝策略是一个接口:
参数:要执行的任务,线程池对象
在这里插入图片描述
默认的实现策略有四个:
在这里插入图片描述

策略一AbortPolicy

在这里插入图片描述

使用:
在这里插入图片描述
源码:
实现拒绝策略接口,覆盖方法,
方法里就是抛异常:信息在异常中打印一下
在这里插入图片描述
异常是运行时异常:
在这里插入图片描述
所以可以try catch, 如果看见这个异常就可以额外处理

运行下用例:
在这里插入图片描述
提交第四个已经抛异常了:
在这里插入图片描述
记录的信息:
把runnable和线程池的信息打印了一下:
在这里插入图片描述

策略二:

不抛异常,有风险也不知道
在这里插入图片描述
使用:
在这里插入图片描述
源码:
实现接口,覆盖方法,方法里是空的,啥事都不做,所以当你任务超过他容量,那么这个是什么都不干,丢弃掉
在这里插入图片描述
代码演示:
在这里插入图片描述
在这里插入图片描述
运行结果:
有一个线程没被执行,抛弃掉了
在这里插入图片描述

策略三

丢弃最老的那个任务,执行当前的任务。
这个策略其实也是给丢掉。所以用的也不多。通常业务不多允许数据丢掉。
在这里插入图片描述
使用:
在这里插入图片描述
也是提交四个任务,分析:
一个核心线程在执行,队列有两个,提交了四个:
在这里插入图片描述
提交四的时候,会把老的丢弃,老的任务是2,所以会把2丢弃。
在这里插入图片描述

运行结果:
在这里插入图片描述
源码:
实现接口,覆盖方法:
如果线程池没有关闭,首先从线程池里拿到他的任务队列,调用poll方法,相当于给队列里移除一个,是队列的头部那个。
老任务删除,再把新任务提交给线程池。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

策略四

就是线程池来执行任务,当线程池已经满了,就用调用线程执行,比如main方法的线程去执行。在这里插入图片描述
代码演示:
在这里插入图片描述
在这里插入图片描述
运行结果:
线程4是由main线程执行的:
在这里插入图片描述
策略源码:
实现接口,覆盖方法:
方法: e线程池有没有关闭,如果没有关闭,直接调runnable的run方法,直接执行这个方法相当于:没有走线程,通过main方法调用的, main方法直接调线程里的run方法。
在这里插入图片描述

自定义拒绝策略

同样实现接口,覆盖方法
在这里插入图片描述

应用场景

一些开源项目实现的拒绝策略

线程池核心工作原理

在这里插入图片描述

线程池底层源码分析

http://www.xdnf.cn/news/755317.html

相关文章:

  • Linux下目录递归拷贝的单进程实现
  • C++读写锁以及实现方式
  • 深入理解短链服务:原理、设计与实现全解析
  • 6级翻译学习
  • 蓝桥云课ROS学习C++教程cpp-geeksforgeeks版本
  • Vue-1-前端框架Vue基础入门之一
  • 6、在树莓派上安装 NTP(Network Time Protocol )服务的步骤
  • Linux --进程状态
  • 论文阅读笔记——Quo Vadis, Action Recognition? A New Model and the Kinetics Dataset
  • 《Python语言程序设计》2018 第4章第9题3重量和价钱的对比,利用第7章的概念来解答你
  • 广东WordPress开发公司及服务
  • 2025年渗透测试面试题总结-奇安信[实习]安全服务工程师(题目+回答)
  • 深入探讨redis:万字讲解集群
  • POJO、DTO和VO:Java应用中的三种关键对象详解
  • 重学计算机网络之以太网
  • 北斗导航 | 高级接收机自主完好性监测算法研究进展
  • 适配器模式:让不兼容接口协同工作
  • 雷达中实信号与复信号
  • 学习BI---BI看板的生命周期
  • MobaXterm国内下载与安装使用教程
  • java27
  • Windows如何定制键盘按键
  • 工作流引擎-11-开源 BPM 项目 jbpm
  • 十三、【核心功能篇】测试计划管理:组织和编排测试用例
  • 【存储基础】NUMA架构
  • 【Python Cookbook】文件与 IO(二)
  • unix/linux source 命令,其历史争议、兼容性、生态、未来展望
  • 从前端工程化角度解析 Vite 打包策略:为何选择 Rollup 而非 esbuild。
  • 鸿蒙OSUniApp集成WebGL:打造跨平台3D视觉盛宴#三方框架 #Uniapp
  • C# await与wait的区别