Java线程池相关讲解
概述
线程池是一种多线程处理形式, 处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务
创建
构造函数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
...
...
...
}
参数详情
-
corePoolSize:核心线程数量,当线程数达corePoolSize时会把到达的任务放到缓存队列
-
maximumPoolSize:线程池中最大能创建的线程的数量
-
keepAliveTime:保证线程存活时间,若线程数超过了corePoolSize,某线程闲置时间超过keepAliveTime时,该线程会被销毁
-
TimeUnit:keepAliveTime时长对应的单位
NANO_SCALE:千分之一微秒
MICRO_SCALE:微秒
MILLI_SCALE:毫秒
SECOND_SCALE:秒
MINUTE_SCALE:分钟
HOUR_SCALE:小时
-
BlockingQueue:阻塞队列,存储等待执行的任务
-
ThreadFactory:创建线程的工厂
-
RejectedExecutionHandler:处理线程池及队列满载后的拒绝请求处理器
线程池工作流程
首先创建一个线程池对象,调用execute()方法添加任务并执行,
如果池中运行的线程数小于corePoolSize,直接启动一个线程去执行当前任务
如果池中运行的线程数大于等于corePoolSize,当前任务会进入等待队列,
如果等待队列满了,总的线程数小于maximumPoolSize,则会创建非核心线程去执行当前任务
如果队列满了,正在运行的线程数大于等于maximumPoolSize,则会抛出异常RejectExecutionException
当一个线程执行完任务后,会从等待队列去一个任务执行,如果一个线程空闲的时间超过keepAliveTime,并且当前运行的内存数超过corePoolSize,该线程就会被停止。
线程池的扩展用法
1.缓存线程池
/**
* 缓存线程池.
* (长度无限制)
* 执行流程:
* 1. 判断线程池是否存在空闲线程
* 2. 存在则使用
* 3. 不存在,则创建线程 并放入线程池, 然后使用
*/
ExecutorService service = Executors.newCachedThreadPool();
//指挥线程池执行新的任务
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午");
}
});
2.定长线程池
/**
* 定长线程池.
* (长度是指定的数值)
* 执行流程:
* 1. 判断线程池是否存在空闲线程
* 2. 存在则使用
* 3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
* 4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
*/
ExecutorService service = Executors.newFixedThreadPool(2);
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
3.单线程线程池
效果与定长线程池 创建时传入数值1 效果一致.
/**
* 单线程线程池.
* 执行流程:
* 1. 判断线程池 的那个线程 是否空闲
* 2. 空闲则使用
* 4. 不空闲,则等待 池中的单个线程空闲后 使用
*/
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午");
}
});
4.周期性任务定长线程池
/**
* 周期任务 定长线程池.
* 执行流程:
* 1. 判断线程池是否存在空闲线程
* 2. 存在则使用
* 3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
* 4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
*
* 周期性任务执行时:
* 定时执行, 当某个时机触发时, 自动执行某任务 .
*/
/**
* 1. 定时执行一次
* 参数1. 定时执行的任务
* 参数2. 时长数字
* 参数3. 时长数字的时间单位 , TimeUnit的常量指定
*/
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("锄禾日当午");
}
},5, TimeUnit.SECONDS);
/**
* 2. 周期性执行任务
* 参数1. 任务
* 参数2. 延迟时长数字(第一次执行在什么时间以后)
* 参数3. 周期时长数字(每隔多久执行一次)
* 参数4. 时长数字单位
*/
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("汗滴禾下土");
}
},5,1,TimeUnit.SECONDS);