自定义线程池

自定义线程池,第1张

第一、什么是线程池
线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队里中,然后在创建线程后自动启动这些任务。这里的任务就是实现了Runnable或Callable接口的实例对象。
第二、为什么使用线程池
使用线程池最大的原因就是可以根据系统的需求和硬件环境灵活的控制线程的数量,且可以对所有线程进行统一的管理和控制,从而提高系统的运行效率,降低系统运行压力;
第三、使用线程池有哪些优势
a.线程和任务分离,提升线程重用性
b.控制线程并发数量,降低服务器压力,统一管理所有线程
c.提升系统响应速度,假如创建线程用的时间为T1,执行任务用的时间为T2,销毁线程用的时间为T3,那么使用线程池就免去了T1和T3的时间。
第四、线程池应用场景
a.网购商品秒杀
b.云盘文件上传和下载
c.12306网上购票系统
总之,只要有并发的地方、任务数量大或小,每个任务执行时间长或短都可以使用线程池。
第五、Java内置线程池ThreadPoolExecutor部分源码

构造方法:
public ThreadPoolExecutor(int corePoolSize, //核心线程数量
	int maximumPoolSize,//最大线程数
	long keepAliveTime, //最大空闲时间
	TimeUnit unit, //时间单位
	BlockingQueue<Runnable> workQueue,//任务队列
    ThreadFactory threadFactory, //线程工厂
	RejectedExecutionHandler handler //饱和处理机制
) 
{ ... }

第六、举例理解上面各个参数
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号工作人员继续待着(池内保持核心线程数量);
第七、线程池工作流程

第八、自定义线程池
1:编写任务类(MyTask),实现Runnable接口;

/**
 * 自定义线程池任务类
 * @author shixiangcheng
 * 2022-05-08
 */
public class MyTask implements Runnable {
	private int 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);//模拟任务执行0.2秒
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("线程:"+name+"完成执行任务:"+id);
	}
	@Override
	public String toString() {
		return "MyTask [id=" + id + "]";
	}
}

2:编写线程类(MyWorker),用于执行任务,需要持有所有任务;

import java.util.List;
/**
 * 自定义线程池线程类
 * @author shixiangcheng
 * 2022-05-08
 */
public class MyWorker extends Thread {
	private String name;//线程名称
	private List<Runnable> taskList;
	public MyWorker(String name,List<Runnable> taskList) {
		super(name);
		this.taskList=taskList;
	}
	@Override
	public void run() {
		//判断集合是否有任务,只要有,就一直执行任务
		while(this.taskList.size()>0) {
			Runnable r=this.taskList.remove(0);
			r.run();
		}
	}
}

3:编写线程池类(MyThreadPool),包含提交任务,执行任务的能力;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
 * 自定义线程池类
 * @author shixiangcheng
 * 2022-05-08
 */
public class MyThreadPool {
	//创建一个线程安全的集合
	private List<Runnable> taskList=Collections.synchronizedList(new LinkedList<Runnable>());
	//当前线程数量
	private int num;
	//核心线程数量
	private int corePoolSize;
	//最大线程数量
	private int maxSize;
	//任务队列长度
	private int workSize;
	public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
		super();
		this.corePoolSize = corePoolSize;
		this.maxSize = maxSize;
		this.workSize = workSize;
	}
	//提交任务
	public void submit(Runnable r) {
		//判断当前集合中任务数量是否超出了最大任务量
		if(this.taskList.size()>=this.workSize) {
			System.out.println("任务:"+r+"被丢弃了");
		}else {
			this.taskList.add(r);
			//执行任务
			execTask(r);
		}
	}
	//执行任务
	public void execTask(Runnable r) {
		//判断当前线程池中的线程总数量是否超出了核心数
		if(num<corePoolSize) {
			new MyWorker("核心线程"+num,taskList).start();
			num++;
		}else if(num<maxSize) {
			new MyWorker("非核心线程"+num,taskList).start();
			num++;			
		}else {
			System.out.println("任务:"+r+"被缓存了");
		}
	}
}

4:编写测试类(Test),创建线程池对象,提交多个任务测试;

/**
 * 测试类
 * @author shixiangcheng
 * 2022-05-08
 */
public class Test {
	public static void main(String [] args) {
		//创建线程池类对象
		MyThreadPool pool=new MyThreadPool(2,4,20);
		//提交多个任务
		for(int i=0;i<10;i++) {
			//创建任务对象,并提交给线程池
			MyTask task=new MyTask(i);
			pool.submit(task);
		}
	}
}

运行测试类

线程:核心线程0即将执行任务:0
线程:核心线程1即将执行任务:2
线程:非核心线程2即将执行任务:1
线程:非核心线程3即将执行任务:3
任务:MyTask [id=4]被缓存了
任务:MyTask [id=5]被缓存了
任务:MyTask [id=6]被缓存了
任务:MyTask [id=7]被缓存了
任务:MyTask [id=8]被缓存了
任务:MyTask [id=9]被缓存了
线程:核心线程0完成执行任务:0
线程:核心线程0即将执行任务:4
线程:非核心线程3完成执行任务:3
线程:核心线程1完成执行任务:2
线程:核心线程1即将执行任务:6
线程:非核心线程2完成执行任务:1
线程:非核心线程2即将执行任务:7
线程:非核心线程3即将执行任务:5
线程:核心线程0完成执行任务:4
线程:核心线程0即将执行任务:8
线程:非核心线程3完成执行任务:5
线程:非核心线程3即将执行任务:9
线程:核心线程1完成执行任务:6
线程:非核心线程2完成执行任务:7
线程:核心线程0完成执行任务:8
线程:非核心线程3完成执行任务:9

欢迎大家积极留言交流学习心得,点赞的人最美丽!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/877089.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存