没有合适的资源?快使用搜索试试~ 我知道了~
相对系统的了解java 线程池的知识点
资源推荐
资源详情
资源评论
线程池详解
什么是线程池
线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线
程后自动启动这些任务。这里的线程就是我们前面学过的线程,这里的任务就是我们前面学
过的实现了 Runnable 或 Callable 接口的实例对象;
为什么使用线程池
使用线程池最大的原因就是可以根据系统的需求和硬件环境灵活的控制线程的数量,且可以
对所有线程进行统一的管理和控制,从而提高系统的运行效率,降低系统运行运行压力;当然
了,使用线程池的原因不仅仅只有这些,我们可以从线程池自身的优点上来进一步了解线程池
的好处;
使用线程池有哪些优势
1:线程和任务分离,提升线程重用性;
2:控制线程并发数量,降低服务器压力,统一管理所有线程;
3:提升系统响应速度,假如创建线程用的时间为 T1,执行任务用的时间为 T2,销毁线程用的时
间为 T3,那么使用线程池就免去了 T1 和 T3 的时间;
只要有并发的地方、任务数量大或小、每个任务执行时间长或短的都可以使用线程池;
只不过在使用线程池的时候,注意一下设置合理的线程池大小即可;(关于如何合理设置线程
池大小在后面的章节中讲解)
ThreadPoolExecutor 部分源码
构造方法:
public ThreadPoolExecutor(int corePoolSize, //核心线程数量
int maximumPoolSize,// 最大线程数
long keepAliveTime, // 最大空闲时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队
列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 饱和处理机制
)
ThreadPoolExecutor 参数详解
我们可以通过下面的场景理解 ThreadPoolExecutor 中的各个参数;
a 客户(任务)去银行(线程池)办理业务,但银行刚开始营业,窗口服务员还未就位(相当于线程池
中初始线程数量为 0),于是经理(线程池管理者)就安排 1 号工作人员(创建 1 号线程执行任务)
接待 a 客户(创建线程);在 a 客户业务还没办完时,b 客户(任务)又来了,于是经理(线程池管理者)
就安排 2 号工作人员(创建 2 号线程执行任务)接待 b 客户(又创建了一个新的线程);假设该银
行总共就 2 个窗口(核心线程数量是 2);紧接着在 a,b 客户都没有结束的情况下 c 客户来了,于
是经理(线程池管理者)就安排 c 客户先坐到银行大厅的座位上(空位相当于是任务队列)等候,
并告知他: 如果 1、2 号工作人员空出,c 就可以前去办理业务;此时 d 客户又到了银行,(工作人
员都在忙,大厅座位也满了)于是经理赶紧安排临时工(新创建的线程)在大堂站着,手持 pad 设
备给 d 客户办理业务;假如前面的业务都没有结束的时候 e 客户又来了,此时正式工作人员都
上了,临时工也上了,座位也满了(临时工加正式员工的总数量就是最大线程数),
于是经理只能按《超出银行最大接待能力处理办法》(饱和处理机制)拒接接待 e 客户;
最后,进来办业务的人少了,大厅的临时工空闲时间也超过了 1 个小时(最大空闲时间),经理就
会让这部分空闲的员工人下班.(销毁线程)但是为了保证银行银行正常工作(有一个
allowCoreThreadTimeout 变量控制是否允许销毁核心线程,默认 false),即使正式工闲着,也不
得提前下班,所以 1、2 号工作人员继续待着(池内保持核心线程数量);
线程池工作流程总结示意图
自定义线程池-参数设计分析
通过观察 Java 中的内置线程池参数讲解和线程池工作流程总结,我们不难发现,要设计一个好
的线程池,就必须合理的设置线程池的 4 个参数;那到底该如何合理的设计 4 个参数的值呢?我
们一起往下看.
4 个参数的设计:
1:核心线程数(corePoolSize)
核心线程数的设计需要依据任务的处理时间和每秒产生的任务数量来确定,例如:执行一个任
务需要 0.1 秒,系统百分之 80 的时间每秒都会产生 100 个任务,那么要想在 1 秒内处理完这
100 个任务,就需要 10 个线程,此时我们就可以设计核心线程数为 10;当然实际情况不可能这
么平均,所以我们一般按照 8020 原则设计即可,既按照百分之 80 的情况设计核心线程数,剩下
的百分之 20 可以利用最大线程数处理;
2:任务队列长度(workQueue)
任务队列长度一般设计为:核心线程数/单个任务执行时间*2 即可;例如上面的场景中,核心线
程数设计为 10,单个任务执行时间为 0.1 秒,则队列长度可以设计为 200;
3:最大线程数(maximumPoolSize)
最大线程数的设计除了需要参照核心线程数的条件外,还需要参照系统每秒产生的最大任务
数决定:例如:上述环境中,如果系统每秒最大产生的任务是 1000 个,那么,最大线程数=(最大任
务数-任务队列长度)*单个任务执行时间;既: 最大线程数=(1000-200)*0.1=80 个;
4:最大空闲时间(keepAliveTime)
这个参数的设计完全参考系统运行环境和硬件压力设定,没有固定的参考值,用户可以根据经
验和系统产生任务的时间间隔合理设置一个值即可;
自定义线程池-实现步骤
1:编写任务类(MyTask),实现 Runnable 接口;
2:编写线程类(MyWorker),用于执行任务,需要持有所有任务;
3:编写线程池类(MyThreadPool),包含提交任务,执行任务的能力;
4:编写测试类(MyTest),创建线程池对象,提交多个任务测试;
MyTask
/*
需求:
自定义线程池练习,这是任务类,需要实现 Runnable;
包含任务编号,每一个任务执行时间设计为 0.2 秒
*/
public class MyTask implements Runnable{
private int id;
//由于 run 方法是重写接口中的方法,因此 id 这个属性初始化可以利用构造方法完成
public MyTask(int id) {
this.id = id;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println("线程:"+name+" 即将执行任务:"+id);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:"+name+" 完成了任务:"+id);
}
@Override
public String toString() {
return "MyTask{" +
"id=" + id +
'}';
}
}
MyWorker
package com.itheima.demo01;
import java.util.List;
/*
需求:
编写一个线程类,需要继承 Thread 类,设计一个属性,用于保存线程的名字;
设计一个集合,用于保存所有的任务;
*/
public class MyWorker extends Thread{
private String name;//保存线程的名字
private List<Runnable> tasks;
//利用构造方法,给成员变量赋值
public MyWorker(String name, List<Runnable> tasks) {
super(name);
this.tasks = tasks;
}
@Override
public void run() {
//判断集合中是否有任务,只要有,就一直执行任务
while (tasks.size()>0){
Runnable r = tasks.remove(0);
r.run();
}
}
}
MyThreadPool
/*
这是自定义的线程池类;
成员变量:
1:任务队列 集合 需要控制线程安全问题
2:当前线程数量
3:核心线程数量
4:最大线程数量
5:任务队列的长度
成员方法
1:提交任务;
将任务添加到集合中,需要判断是否超出了任务总长度
2:执行任务;
判断当前线程的数量,决定创建核心线程还是非核心线程
*/
public class MyThreadPool {
// 1:任务队列 集合 需要控制线程安全问题
private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());
//2:当前线程数量
private int num;
//3:核心线程数量
private int corePoolSize;
//4:最大线程数量
private int maxSize;
//5:任务队列的长度
private int workSize;
public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
剩余17页未读,继续阅读
资源评论
凝小飞
- 粉丝: 1845
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功