前言
- 为什么要创建线程池:
频繁的创建线程和关闭线程会占用系统资源,增加系统负担,降低系统性能 - 线程池原理:
请求保存下来(如:队列),等有可用线程时就让线程从队列里取出一个请求进行处理 - 线程池大小:
一般需要根据任务的类型来配置线程池大小, 如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1。如果是IO密集型任务,参考值可以设置为2*NCPU
通过ThreadPoolExecutor来创建一个线程池
4个构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数说明
- corePoolSize: 核心线程数,默认情况下核心线程会一直存活,不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut(true)设置为true。
- maximumPoolSize:线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。
- keepAliveTime:非核心线程的闲置超时时间,超过这个时间就会被回收。
- unit :指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。
- workQueue :线程池中的任务队列。常用的队列有,SynchronousQueue,LinkedBlockingDeque
- threadFactory :线程工厂,提供创建新线程的功能。通过线程工厂可以对线程的一些属性进行定制,ThreadFactory是一个接口,只有一个方法
public interface ThreadFactory {
Thread newThread(Runnable r);
}
- RejectedExecutionHandler:当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法。 也是一个接口,只有一个方法。
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable var1, ThreadPoolExecutor var2);
}
线程池规则
线程池的线程执行规则跟任务队列有很大的关系。
- 线程数量<=核心线程数量
那么直接启动一个核心线程来执行任务,不会放入队列中。 - 线程数量>核心线程数,但<=最大线程数,任务队列是LinkedBlockingDeque时
超过核心线程数量的任务会放在任务队列中排队。 - 线程数量>核心线程数,但<=最大线程数,任务队列是SynchronousQueue时
线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。
这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。 - 线程数量>核心线程数,并且>最大线程数,任务队列是LinkedBlockingDeque时
会将超过核心线程的任务放在任务队列中排队。 - 线程数量>核心线程数,并且>最大线程数,任务队列是SynchronousQueue的时候,
会因为线程池拒绝添加任务而抛出异常。
实例
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 一个简单的线程池使用示例
*/
public class TestThreadPoolExecutor {
public static void main(String[] args) {
// 核心线程数
int corePoolSize = 2;
// 最大线程数
int maximumPoolSize = 10;
// 非核心线程的闲置超时时间
long keepAliveTime = 60;
// keepAliveTime的单位
TimeUnit unit = TimeUnit.SECONDS;
// 线程池中的任务队列
BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue);
// threadPoolExecutor.allowCoreThreadTimeOut(true);
//调用execute执行任务
for (int i = 0; i < maximumPoolSize + 1; i++) {
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName=" + Thread.currentThread().getName());
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
//终止空闲线程,并等待任务执行完成或超过10秒之后退出
try {
threadPoolExecutor.shutdown();
threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS);
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}