Java中有界队列的饱和策略的用法

  介绍

这篇文章主要讲解了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中有界队列的饱和策略的用法