现在做开发的童鞋,越来越多的人在创建线程池用ThreadPoolExecutor,而不是用JDK提供的四种方法来创建
一、线程池的背景:
1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
2、可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。
二、核心参数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
corePoolSize:线程池核心线程数量
maximumPoolSize:线程池最大线程数量
keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
unit:存活时间的单位
workQueue:存放任务的队列
handler:超出线程范围和队列容量的任务的处理程序
三、实现原理:
提交一个任务到线程池中,线程池的处理流程如下:
1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。
2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
采用ThreadPoolExecutor创建的优点:
- 可以实时获取线程池内线程的各种状态
- 可以动态调整线程池大小
/**
* ThreadPoolExecutor类的使用方法
* 实现高并发:在线程类中的run()方法内设置Thread.sleep(long delta); delta取值为:(并发开始时间戳 - 线程开始时间戳)
* Created by Administrator on 2016/11/19.
*/
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
//设置核心池大小
int corePoolSize = 5;
//设置线程池最大能接受多少线程
//当前线程数大于corePoolSize、小于maximumPoolSize时,超出corePoolSize的线程数的生命周期
long keepActiveTime = 200;
//设置时间单位,秒
TimeUnit timeUnit = TimeUnit.SECONDS;
//设置线程池缓存队列的排队策略为FIFO,并且指定缓存队列大小为5
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5);
//创建ThreadPoolExecutor线程池对象,并初始化该对象的各种参数
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepActiveTime, timeUnit,workQueue);
//往线程池中循环提交线程
for (int i = 0; i < 15; i++) {
//创建线程类对象
MyTask myTask = new MyTask(i);
//开启线程
executor.execute(myTask);
//获取线程池中线程的相应参数
System.out.println("线程池中线程数目:" +executor.getPoolSize() + ",队列中等待执行的任务数目:"+executor.getQueue().size() + ",已执行完的任务数目:"+executor.getCompletedTaskCount());
}
//待线程池以及缓存队列中所有的线程任务完成后关闭线程池。
executor.shutdown();
}
}
/**
*线程类
*/
class MyTask implements Runnable {
private int num;
public MyTask(int num) {
this.num = num;
}
@Override
public void run() {
System.out.println("正在执行task " + num );
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + num + "执行完毕");
}
/**
* 获取(未来时间戳-当前时间戳)的差值,
* 也即是:(每个线程的睡醒时间戳-每个线程的入睡时间戳)
* 作用:用于实现多线程高并发
* @return
* @throws ParseException
*/
public long getDelta() throws ParseException {
//获取当前时间戳
long t1 = new Date().getTime();
//获取未来某个时间戳(自定义,可写入配置文件)
String str = "2016-11-11 15:15:15";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long t2 = simpleDateFormat.parse(str).getTime();
return t2 - t1;
}
}