一、基本概念
线程池是在实际项目中经常使用的一种技术,它可以提高程序的效率,同时也可以避免频繁的线程创建和销毁的开销。线程池中包含着若干个线程,这些线程能够接收程序传递过来的任务,并按照一定的策略来执行这些任务。在线程池中,拒绝策略用于处理当线程池中的线程资源不足时,向调用者返回一种拒绝策略,从而防止任务队列中的任务出现无法被处理的情况。
二、线程池拒绝策略类型
Java中定义了四种拒绝策略,在使用线程池的时候可以根据实际情况选择合适的拒绝策略,避免任务队列中的任务无法被处理。下面我们来逐一介绍这四种线程池拒绝策略类型:
1. CallerRunsPolicy
如果线程池中的线程已经达到最大并发数,而且等待队列已经被填满,那么新提交的任务将在调用这个线程池的execute()方法的线程中执行,也就是说,这个任务是会在提交这个任务的线程中执行的。这种情况下,由于任务是在调用者线程中执行,因此执行效率可能会受到一定的影响。
public class CallerRunsPolicy implements RejectedExecutionHandler { public CallerRunsPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } }
2. AbortPolicy
这是线程池的默认拒绝策略。如果线程池中的线程已经达到最大并发数,而且等待队列已经被填满,那么新提交的任务将会被抛弃,并抛出RejectedExecutionException异常。
public class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
3. DiscardPolicy
这种策略会直接将新提交的任务抛弃,不做任何处理。如果队列满了,那么后续的任务就会被忽略掉。
public class DiscardPolicy implements RejectedExecutionHandler { public DiscardPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }
4. DiscardOldestPolicy
这种策略会将最早提交的任务从队列中移除,然后尝试再次执行新提交的任务。
public class DiscardOldestPolicy implements RejectedExecutionHandler { public DiscardOldestPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } }
三、自定义拒绝策略
如果以上四种拒绝策略不能够满足实际需求,我们可以自己定义一种新的拒绝策略。在定义新的拒绝策略时,我们只需要实现RejectedExecutionHandler接口,并重写其中的rejectedExecution方法就可以了。
public class CustomPolicy implements RejectedExecutionHandler { public CustomPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { // 自定义处理逻辑 } }
四、总结
线程池是一种非常常用的技术,它可以避免频繁的线程创建和销毁的开销,提高程序的效率。在使用线程池时,线程池拒绝策略起着非常重要的作用,能够防止任务队列中的任务出现无法被处理的情况。在Java中,定义了四种线程池拒绝策略类型,使用者可以根据具体的情况进行选择。同时,Java也支持自定义拒绝策略,当以上四种类型无法满足实际需求时,我们可以根据实际情况定义新的拒绝策略。