一、池化思想
例如:数据库连接池、字符串常量池、线程池
作用:频繁地创建和销毁线程会导致系统开销增大,利用池化思想可以提高资源的利用率;
优点:
1、提高线程利用率;
2、提高程序响应速度;
3、便于统一管理线程对象;
4、可以控制最大并发数
二、线程池的参数
1、核心线程数 (corePoolSize):这是线程池在没有任务执行时保持存活的线程数,即使这些线程处于空闲状态。如果线程池的当前线程数小于这个值,则新提交的任务将创建一个新线程来处理请求,即使其他线程空闲。
2、最大线程数 (maximumPoolSize):这是线程池允许创建的最大线程数。当任务数量超出核心线程数时,线程池会逐步增加线程数,但不会超过这个数值。
3、空闲线程存活时间 (keepAliveTime):当线程池中的线程数量超过核心线程数时,多余的线程在空闲状态下的最长存活时间。一旦超过这个时间,这些空闲线程会被终止,以减少系统资源的消耗。
4、时间单位 (unit):与 keepAliveTime 参数配合使用,用于指定 keepAliveTime 参数的时间单位。
5、工作队列 (workQueue):用于存放等待执行的任务的阻塞队列。不同的工作队列实现可以影响任务的调度和执行策略。
6、线程工厂 (threadFactory):用于创建新线程的工厂类。可以通过自定义线程工厂来设置线程的名称、优先级等。
7、拒绝执行处理器 (handler):当线程池和工作队列都满了,无法接受新任务时,会调用这个处理器来决定如何处理新提交的任务。
三、创建多个线程时各参数执行先后顺序
1、当前线程数小于核心线程数,当前线程直接运行。
2、当前线程数大于核心线程数,当前线程会加入到阻塞队列中,
3、此时阻塞队列未满,直接加入,等待机会运行。
4、此时阻塞队列已满,但此时线程数小于最大线程数,则直接创建线程运行。
5、此时线程数大于等于最大线程数,则实行线程池自定义的拒绝策略。
四、代码
public class TestExecutor {
@Test
public void testCoreExecutor() {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
1L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(3),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy());//拒绝策略,抛异常
for (int i = 0; i < 3; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
});
}
}
@Test
public void testExecutorQueue() {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
1L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy());//拒绝策略,抛异常
for (int i = 0; i < 5; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
});
}
}
@Test
public void testMaxExecutor() {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
1L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy());//拒绝策略,抛异常
for (int i = 0; i < 7; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
});
}
}
@Test
public void testAbortPolicy() {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
1L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy());//拒绝策略,抛异常
for (int i = 0; i < 100; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
});
}
}
}
五、拒绝策略分类
1、AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
@Test
public void testAbortPolicy() throws Exception {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
10L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy());//拒绝策略,抛异常
for (int i = 0; i <8; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
// 关闭线程池
threadPoolExecutor.shutdown();
//等待执行完
threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS);
}
pool-1-thread-1---办理业务
pool-1-thread-2---办理业务
pool-1-thread-3---办理业务
pool-1-thread-5---办理业务
pool-1-thread-4---办理业务
java.util.concurrent.RejectedExecutionException: Task com.ly.TestExecutor$$Lambda$1/1805013491@7113b13f rejected from java.util.concurrent.ThreadPoolExecutor@42d8062c[Running, pool size = 5, active threads = 5, queued tasks = 2, completed tasks = 0]
2、DiscardPolicy:丢弃任务,但是不抛出异常。
@Test
public void testAbortPolicy() throws Exception {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
10L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.DiscardPolicy());//拒绝策略,抛异常
for (int i = 0; i <10; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
// 关闭线程池
threadPoolExecutor.shutdown();
//等待执行完
threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS);
}
com.ly.TestExecutor,testAbortPolicy
Connected to the target VM, address: '127.0.0.1:6834', transport: 'socket'
pool-1-thread-1---办理业务
pool-1-thread-2---办理业务
pool-1-thread-3---办理业务
pool-1-thread-4---办理业务
pool-1-thread-5---办理业务
pool-1-thread-2---办理业务
pool-1-thread-5---办理业务
Disconnected from the target VM, address: '127.0.0.1:6834', transport: 'socket'
3、CallerRunsPolicy:由调用线程(提交任务的线程,一般是主线程)处理该任务
@Test
public void testAbortPolicy() throws Exception {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
10L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.CallerRunsPolicy());//拒绝策略,抛异常
for (int i = 0; i <10; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
// 关闭线程池
threadPoolExecutor.shutdown();
//等待执行完
threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS);
}
pool-1-thread-1---办理业务
pool-1-thread-3---办理业务
pool-1-thread-2---办理业务
pool-1-thread-4---办理业务
main---办理业务
pool-1-thread-5---办理业务
main---办理业务
pool-1-thread-1---办理业务
pool-1-thread-2---办理业务
pool-1-thread-2---办理业务
4、DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
@Test
public void testPolicy() throws Exception {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,//核心线程数
5,//最大线程数
10L,//线程空闲时保存时间
TimeUnit.SECONDS,//线程空闲时保存时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.DiscardOldestPolicy());//拒绝策略,抛异常
for (int i = 0; i <10; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"---办理业务");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
// 关闭线程池
threadPoolExecutor.shutdown();
//等待执行完
threadPoolExecutor.awaitTermination(60, TimeUnit.SECONDS);
}
pool-1-thread-1---办理业务
pool-1-thread-2---办理业务
pool-1-thread-3---办理业务
pool-1-thread-4---办理业务
pool-1-thread-5---办理业务
pool-1-thread-3---办理业务
pool-1-thread-4---办理业务