这篇文章主要讲解了Java中有界队列的饱和策略的用法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
我们在使用ExecutorService的时候知道,在ExecutorService中有个一个队列来保存提交的任务,通过不同的构造函数,我们可以创建无界的队列(ExecutorService。newCachedThreadPool)和有界的队列(ExecutorService newFixedThreadPool (int nThreads)。
无界队列很好理解,我们可以无限制的向ExecutorService提交任务。那么对于有界队列来说,如果队列满了该怎么处理呢?
今天我们要介绍一下java中ExecutorService的饱和策略(拒绝政策)。
以ExecutorService的具体实现ThreadPoolExecutor来说,它定义了4种饱和策略。分别是AbortPolicy, DiscardPolicy, DiscardOldestPolicy和CallerRunsPolicy。
如果要在ThreadPoolExecutor中设定饱和策略可以调用setRejectedExecutionHandler方法,如下所示:
ThreadPoolExecutor ThreadPoolExecutor=new ThreadPoolExecutor (5、10、10、TimeUnit。秒,新LinkedBlockingDeque(20)); threadPoolExecutor.setRejectedExecutionHandler ( 新的ThreadPoolExecutor.AbortPolicy () );
上面的例子中我们定义了一个初始5个,最大10个工作线程的线程池,并且定义其中的队列的容量是20。如果提交的任务超出了容量,则会使用AbortPolicy策略。
<强> AbortPolicy 强>
AbortPolicy意思是如果队列满了,最新的提交任务将会被拒绝,并抛出RejectedExecutionException异常:
公共静态类AbortPolicy实现RejectedExecutionHandler {/* * *创建一个{@code AbortPolicy}。 */公共AbortPolicy () {}/* * *总是抛出RejectedExecutionException。 * * @param r runnable任务要求被执行 * @param e执行程序试图执行此任务 * @throws RejectedExecutionException总是 */公共空间rejectedExecution (Runnable r, ThreadPoolExecutor e) { 把新的RejectedExecutionException(“任务”;+ + r.toString () “;从“拒绝;+ e.toString ()); } }
上面的代码中,rejectedExecution方法中我们直接抛出了RejectedExecutionException异常。
<强> DiscardPolicy 强>
DiscardPolicy将会悄悄的丢弃提交的任务,而不报任何异常。
公共静态类DiscardPolicy实现RejectedExecutionHandler {/* * *创建一个{@code DiscardPolicy}。 */公共DiscardPolicy () {}/* * *没有,丢弃任务r的影响。 * * @param r runnable任务要求被执行 * @param e执行程序试图执行此任务 */公共空间rejectedExecution (Runnable r, ThreadPoolExecutor e) { } }
<>强DiscardOldestPolicy
强>
DiscardOldestPolicy将会丢弃最老的任务,保存最新插入的任务。
公共静态类DiscardOldestPolicy实现RejectedExecutionHandler {/* * *创建一个{@code DiscardOldestPolicy}为给定的遗嘱执行人。 */公共DiscardOldestPolicy () {}/* * *获得,而忽略了遗嘱执行人的下一个任务 *否则执行,如果>公共静态类CallerRunsPolicy实现RejectedExecutionHandler {/* * *创建一个{@code CallerRunsPolicy}。 */公共CallerRunsPolicy () {}/* * *执行任务在调用者# 39;r s线程,除非遗嘱执行人 *已经关闭,在这种情况下,任务就会被丢弃。 * * @param r runnable任务要求被执行 * @param e执行程序试图执行此任务 */公共空间rejectedExecution (Runnable r, ThreadPoolExecutor e) { 如果(! e.isShutdown ()) { r.run (); } } }
在rejectedExecution方法中,直接调用了r.run()方法,这会导致该方法直接在调用者的主线程中执行,而不是在线程池中执行。从而导致主线程在该任务执行结束之前不能提交任何任务。从而有效的阻止了任务的提交。
<强>使用信号量强>
如果我们并没有定义饱和策略,那么有没有什么方法来控制任务的提交速度呢?考虑下之前我们讲到的信号,我们可以指定一定的资源信号量来控制任务的提交,如下所示:
公共类SemaphoreUsage { 私人最后的遗嘱执行人执行人; 私人最终信号信号量; 公共SemaphoreUsage(执行人执行人,int数){ 这一点。遗嘱执行人=执行人; 这一点。信号量=new信号量(数量); } 公共空间submitTask(最终可运行命令)抛出InterruptedException { semaphore.acquire (); 尝试{ executor.execute (()→{ 尝试{ command.run (); 最后}{ semaphore.release (); } } ); }捕捉(RejectedExecutionException e) { semaphore.release (); } } }Java中有界队列的饱和策略的用法