目录
一、什么是线程池?
二、线程池的好处
三、线程池的执行流程
四、线程池的四种拒绝策略
一、什么是线程池?
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。线程池中的线程由系统管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
二、线程池的好处
- 提高响应速度;
- 降低资源消耗,不用频繁的创建和销毁线程;
- 提高线程的可管理性。
三、线程池的执行流程
-
每过来一个任务会启动一个核心线程去执行
-
当核心线程数用完后,会把新来的任务存入阻塞队列中;
-
阻塞队列存满后,会再启动超过核心线程数量到最大线程数量之间的线程;
-
当线程的数量达到最大线程数量,再来任务就启动拒绝策略。
四、线程池的四种拒绝策略
策略 |
处理方式 |
AbortPolicy |
直接抛出异常 |
DiscardPolicy |
丢弃当前被拒绝的任务(而不抛出任何异常) |
DiscardOldestPolicy |
将工作队列中最老的任务丢弃,然后重新尝试接纳被拒绝的任务 |
CallerRunsPolicy |
在客户端线程中执行被拒绝的任务 |
package policy;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
//for(;;);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--------------------");
}
};
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("aaaaaaaaaaaaa");
}
};
ThreadPoolExecutor pool = new ThreadPoolExecutor(1,
2,
10,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(1),
Executors.defaultThreadFactory(),
new AbortPolicy());
//new DiscardPolicy());
//new DiscardOldestPolicy());
//new CallerRunsPolicy());
pool.execute(r);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}//保证线程已经开始执行任务
//获取当前线程池中线程的数量
int size = pool.getPoolSize();
System.out.println(size);
pool.execute(r);
size = pool.getPoolSize();
System.out.println(size);
pool.execute(r);
size = pool.getPoolSize();
System.out.println(size);
pool.execute(r1);
size = pool.getPoolSize();
System.out.println(size);
//关闭线程池
pool.shutdown();
}
}
1.AbortPolicy
线程池的默认策略,当线程池中核心线程数量、最大线程数量和阻塞队列都满时,才会启动拒绝策略。AbortPolicy就是直接抛出异常。

2.DiscardPolicy
Discardpolicy策略会拒绝执行新来的线程,但不抛出异常。

相同的代码,可以看出DiscardPolicy和AbortPolicy的区别。
3.DiscardOldestPolicy
DiscardOldestPolicy策略,会丢掉队伍中最早的任务,来尝试执行新来的任务。

通过运行结果我们可以看出,新来的任务被执行了。
4.CallerRunsPolicy
CallerRunsPolicy策略不会像DiscardOldestPolicy一样去丢掉线程池中的任务,它会在客户端线程中执行被拒绝的任务。

由此我们可以看出, CallerRunsPolicy策略下的任务并不会影响线程池中的其他任务。
以上就是线程池常用的四种策略,四种策略效果不同,可以在不同的场景中去设置不同类型的拒绝策略。