存放多个线程对象的资源池
用于提高启动多个线程的性能(类比连接池)
当程序中涉及创建大量生存期很短的线程,推荐使用线程池。
线程池类的层次图:
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); } }
运行结果
问题:调度线程池中的线程是否跟任务绑定,还是到调度时间,重新分配? 回答:通过上图画红线得出答案,是到调度时间重新分配。