java-手撕一个线程池

版权声明:fromZjy QQ1045152332 https://blog.csdn.net/qq_36762677/article/details/82904121

线程池作用

  • 降低资源消耗(重复利用已创建的线程)
  • 提高响应速度(任务到达时,不需要等待创建线程)
  • 提高线程的可管理性(线程是稀缺资源,线程池可以进行统一分配、调优和监控)

不用线程池

如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),况且我们还不能控制线程池中线程的开始、挂起、和中止。

Executor线程池构造4种线程池

Java通过Executors(jdk1.5并发包)提供四种线程池
Executor框架的最顶层实现是ThreadPoolExecutor类,Executors工厂类中提供的newScheduledThreadPool、newFixedThreadPool、newCachedThreadPool方法其实也只是ThreadPoolExecutor的核心构造函数参数不同而已。通过传入不同的参数,就可以构造出适用于不同应用场景下的线程池,那么它的底层原理是怎样实现的呢,这篇就来介绍下ThreadPoolExecutor线程池的运行过程。

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

ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
newCachedThreadPool.execute(new Runable(){
	@Override
	public void run(){
	}
});

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

//最大三个线程的线程池
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
newFixedThreadPool.execute(new Runable(){
	@Override
	public void run(){
	}
});

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

ExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool();
newScheduledThreadPool.execute(new Runable(){
	@Override
	public void run(){
	}
});

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

corePoolSize: 核心池的大小。 当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中
maximumPoolSize: 线程池最大线程数,它表示在线程池中最多能创建多少个线程;
keepAliveTime: 表示线程没有任务执行时最多保持多久时间会终止。
unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

设计一个线程池

1)线程池管理类[单例设计模式]
主要用于实现创建线程和添加线程处理的新任务,执行任务以及如何回收已经执行完任务的线程。
增加任务的方法(addTask)、批量增加任务的方法(batchAddTask)、得到实例的方法(getInstanse)以及执行任务的方法(execute)

//增加任务的方法
public void addTask(Task task){
	lock.lock();
	taskQueue.add(task);
	taskQueue.notifyAll();
	lock.unlock();
}

//执行任务的方法
public void execute(){
	for(int i=0; i<workThreads.length; i++){
	WorkThread wt = workThreads[i];
	if(wt.isWaiting()){
	new Thread(wt).start();
	break;
	}
}

2)工作线程类
线程池中的线程,也实现了Runnable接口,它主要用于处理任务队列中的任务。
在run()方法里面它首先判断任务队列里面是否有任务,如果没有就等待新任务加入,如果有任务就从任务队列中取出任务并执行,在线程池中可以设定工作线程的个数

while(isRunning){
	lock.lock();
	while(taskQueue.isEmpty()){
		try{
			taskQueue.wait();
		}catch(Exception e){
		}
	}
	task = (Task)taskQueue.remove(0);
	try{
		new Thread(task).start();
	}catch(Exception e){
		e.printStackTrace();
	}
	lock.unlock();
	}
}

3)任务类
定义任务的各种属性,以及要执行的操作

public class Task implements Runnable{
	public void run(){
	}
}

4)任务队列 Map、Set以及List
按先来先服务的顺序用于存放新加入的任务,以便让工作线程来执行
在文中通过Collections.synchronizedList将其转换为一个线程安全的类。任务队列定义如下所示:

private List<Task> taskQueue = Collections.synchronizedList(new LinkedList<Task>());

猜你喜欢

转载自blog.csdn.net/qq_36762677/article/details/82904121