大家好,欢迎来到IT知识分享网。
共用四种拒绝策略分别为: AbortPolicy,CallerRunsPolicy,DiscardPolicy,DiscardOldestPolicy 它们都是 ThreadPoolExecutor 类下的静态内部类,并都实现了 RejectExecutionHandler 接口;
下面的 MyRunnable 类用来描述一个任务
class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + " 正在执行 " + System.currentTimeMillis()); try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
1. AbortPolicy:
触发该拒绝策略时,会直接抛出 RejectedExecutionException 异常;
public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.AbortPolicy()); MyRunnable runnable1 = new MyRunnable(); MyRunnable runnable2 = new MyRunnable(); MyRunnable runnable3 = new MyRunnable(); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); }
抛出异常之后,此时新的任务也无法继续完成了,但是在阻塞队列中存在的任务并非是新的任务;所以等待 2 秒(因为 MyRunnable 接口 重写的 run 方法 sleep 了 2 秒)之后,此时线程会继续执行阻塞队列中的任务;看下面这个情况:
Thread.sleep(3000); System.out.println(System.currentTimeMillis()); MyRunnable runnable4 = new MyRunnable(); executor.execute(runnable4);
在上述代码的基础上,再添加以上代码,再次执行程序:
可以看到,本来应该是执行完阻塞队列的任务之后,主线程休眠 3 秒,执行阻塞队列的任务会休眠2 秒,所以主线程休眠 3 秒之后,线程应该是空闲状态,理应继续执行下面的逻辑,打印当前时间戳,并执行任务 4,但是使用的是 AbortPolicy 拒绝策略,抛出异常后,后续任务也不会执行了;
2. CallerRunsPolicy:
触发该拒绝策略时,添加的任务由添加任务的线程执行;
public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.CallerRunsPolicy()); MyRunnable runnable1 = new MyRunnable(); MyRunnable runnable2 = new MyRunnable(); MyRunnable runnable3 = new MyRunnable(); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); }
由执行结果可以看到,第一个任务由线程池的核心线程执行, 第二个任务进入阻塞队列并等待执行,第三个任务会触发拒绝策略 CallerRunsPolicy,由添加任务的线程执行,显然此处是 main 线程添加的任务,故由 main 线程执行,核心线程经过 2 秒执行完毕后,继续执行阻塞队列中的任务;此时,如果有新任务再次添加,结果又会怎么样呢?同样添加上述代码,测试结果如下:
Thread.sleep(3000); System.out.println(System.currentTimeMillis()); MyRunnable runnable4 = new MyRunnable(); executor.execute(runnable4);
可以看出,触发 CallerRunsPolicy 拒绝策略之后,再有新任务来时,仍然能正常执行;
3. DiscardOldestPolicy:
触发该拒绝策略时,会丢弃一个阻塞队列中最古老的任务,并将新的任务加入到阻塞队列中;
为了验证该拒绝策略,对 MyRunnable 类添加一个属性 name,并对 run 方法进行调整:
class MyRunnable implements Runnable{ private String name; public MyRunnable(String name){ this.name = name; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " 正在执行 " + this.name + " 时间 " + System.currentTimeMillis()); try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardOldestPolicy()); MyRunnable runnable1 = new MyRunnable("第一个任务"); MyRunnable runnable2 = new MyRunnable("第二个任务"); MyRunnable runnable3 = new MyRunnable("第三个任务"); MyRunnable runnable4 = new MyRunnable("第四个任务"); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); executor.execute(runnable4); Thread.sleep(3000); System.out.println("所有任务执行完毕"); }
由代码及运行结果可以看出,首先第一个任务来时,由核心线程执行,第二个任务来时,进入阻塞队列,第三个任务来时,线程全部都不空闲,并且阻塞队列已满,故会触发拒绝策略,丢弃第二个任务,并将第三个任务放入阻塞队列,第四个任务来时,仍然会触发拒绝策略,丢弃第三个任务,并将第四个任务放入阻塞队列,之后核心线程执行完第一个任务之后,会继续执行阻塞队列中的第四个任务;
4. DiscardPolicy:
触发该拒绝策略时,会直接丢弃掉新来的任务,即直接忽略;
public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardPolicy()); MyRunnable runnable1 = new MyRunnable("第一个任务"); MyRunnable runnable2 = new MyRunnable("第二个任务"); MyRunnable runnable3 = new MyRunnable("第三个任务"); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); Thread.sleep(3000); System.out.println("所有任务执行完毕"); }
由代码及运行结果可以看出,首先第一个任务来时,由核心线程执行,第二个任务来时,进入阻塞队列,第三个任务来时,会触发 DiscardPolicy 拒绝策略,直接丢弃第三个任务,等待核心线程执行完第一个任务之后,会继续执行阻塞队列中的第二个任务;
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/114521.html







