Java多线程之线程池详解

线程池概念

存放多个线程对象的资源池
用于提高启动多个线程的性能(类比连接池)
当程序中涉及创建大量生存期很短的线程,推荐使用线程池。

内置线程池

  1. SingleThreadPool:创建一个单线程化的线程池,只有唯一一个线程来执行任务,保证所有任务按照指定顺序执行(可能是先进先出,后进先出,优先级别)
  2. FixedThreadPool:创建可以可以重用的固定数量的线程池。
  3. CachedThreadPool:创建一个根据需要可新增线程的线程池。
  4. ScheduledThreadPool:创建一个定长的线程池,支持定时及周期性任务调度。

线程池源码简单解析

线程池类的层次图:
在这里插入图片描述

Executor:顶层接口,接受线程任务并且执行
在这里插入图片描述
ExecutorService:添加了一些其他方法。ThreadPoolExecutor:添加了一些常规的线程池,Single,Fixed,Cached
在这里插入图片描述
或许有的同学觉得这几参数比较难理解所以我这给出一个简化版本

corePoolSize - 核心线程数
maximumPoolSize - 最大线程数。
keepAliveTime - 线程存活时间
unit -时间单位设置
keepAliveTime-任务缓存队列

Executor:工具类,创建不同的线程池。
ScheduleThreadPoolExecutor:调度的线程池

线程池的简单应用

SingleThreadPool

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest01 {
public static void main(String[] args) {
	//创建SingleThreadPool线程池
	ExecutorService pool  = Executors.newSingleThreadExecutor();
	//创建FixedThreadPool线程池,并且定义为3个线程的线程池
	ExecutorService pool = Executors.newFixedThreadPool(3); 
	//创建CachedThreadPool线程池
	ExecutorService pool = Executors.newCachedThreadPool();
	
	 //创建很多个任务
	TaskTest t1 = new TaskTest("t1");//创建任务1
	TaskTest t2 = new TaskTest("t2");//创建任务2
	TaskTest t3 = new TaskTest("t3");//创建任务3
	TaskTest t4 = new TaskTest("t4");//创建任务4
	TaskTest t5 = new TaskTest("t5");//创建任务5
	pool.execute(t1);//执行t1
	pool.execute(t2);//执行t2
	pool.execute(t3);//执行t3
	pool.execute(t4);//执行t4
	pool.execute(t5);//执行t5
	
	pool.shutdown();//关闭
	
}
}
class TaskTest implements Runnable{
private String name; //任务名字	

	public TaskTest(String name) {

	this.name = name;
}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+"正在执行"+name);
	}
	
}

SingleThreadPool运行结果 在这里插入图片描述
可以看出,所有任务都是由线程1来完成的,满足只有唯一一个线程来执行任务,保证所有任务按照指定顺序执行。

FixedThreadPool运行结果:
在这里插入图片描述
满足所有线程都由创建的三个线程来完成

CachedThreadPool运行结果:
在这里插入图片描述
满足线程的增加

调度线程池

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorTest02 {
public static void main(String[] args) {
	SET t1 = new SET("t1");
	SET t2 = new SET("t2");
	//创建有两个线程的调度线程池
	ScheduledThreadPoolExecutor sche = new ScheduledThreadPoolExecutor(2);
	sche.scheduleAtFixedRate(t1,1,1,TimeUnit.SECONDS);//设置t1调度参数
	sche.scheduleAtFixedRate(t2,1,1,TimeUnit.SECONDS);//设置t2调度参数
}
	
}
class SET implements Runnable{
private String name; //任务名字	

	public SET(String name) {

	this.name = name;
}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+"正在执行"+name);
	}
	
}

运行结果
在这里插入图片描述

问题:调度线程池中的线程是否跟任务绑定,还是到调度时间,重新分配? 回答:通过上图画红线得出答案,是到调度时间重新分配。