Java 之ThreadPoolExecutor.RejectedExecutionHandler

 

  • ThreadPoolExecutor.AbortPolicy()抛出java.util.concurrent.RejectedExecutionException异常 终止策略是默认的饱和策略;
  • ThreadPoolExecutor.CallerRunsPolicy()当抛出RejectedExecutionException异常时,会调rejectedExecution方法 调用者运行策略实现了一种调节机制,该策略既不会抛弃任务也不会爆出异常,而是将任务退回给调用者,从而降低新任务的流量
  • ThreadPoolExecutor.DiscardOldestPolicy()抛弃旧的任务;当新提交的任务无法保存到队列中等待执行时将抛弃最旧的任务,然后尝试提交新任务。如果等待队列是一个优先级队列,抛弃最旧的策略将导致抛弃优先级最高的任务,因此AbortPolicy最好不要和优先级队列一起使用。
  • ThreadPoolExecutor.DiscardPolicy()抛弃当前的任务

 

/**
 *返回给调用者的饱和策略
 * @author zhangwei_david
 * @version $Id: CallerRunsTestClient.java, v 0.1 2014年11月13日 下午3:14:58 zhangwei_david Exp $
 */
public class CallerRunsTestClient {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        //等待队列
        final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(5);
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 5, 2, TimeUnit.SECONDS, queue);

        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 15; i++) {
            executor.execute(new Runnable() {

                public void run() {
                    System.out.println("run-" + Thread.currentThread().getName() + " queue:"
                                       + queue.size());
                    try {
                        TimeUnit.SECONDS.sleep(20);
                    } catch (InterruptedException e) {
                        //logger.error("", e);
                    }
                }
            });
        }
    }

}

 运行的结果是:可以在日志中看有两次是在主线程中运行的

run-pool-1-thread-1 queue:5
run-pool-1-thread-2 queue:5
run-pool-1-thread-3 queue:5
run-main queue:5
run-pool-1-thread-4 queue:5
run-pool-1-thread-5 queue:5
run-pool-1-thread-1 queue:4
run-pool-1-thread-3 queue:2
run-pool-1-thread-2 queue:3
run-main queue:5
run-pool-1-thread-5 queue:4
run-pool-1-thread-4 queue:3
run-pool-1-thread-2 queue:1
run-pool-1-thread-1 queue:1
run-pool-1-thread-3 queue:0

 终止饱和策略是,当提交的任务无法进入等待队列且线程池中创建的线程数量已经达到了最大线程数量的限制,则会拒绝新提交的任务。

/**
 *终止饱和策略
 * @author zhangwei_david
 * @version $Id: AbortTestClient.java, v 0.1 2014年11月13日 下午3:03:47 zhangwei_david Exp $
 */
public class AbortTestClient {

    public static void main(String[] args) {

        final ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 2, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(5));

        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());

        executor.setThreadFactory(new MyThreadFactory("Test"));

        for (int i = 0; i < 10; i++) {
            try {
                executor.execute(new Runnable() {

                    public void run() {
                        //doNothing
                    }
                });
            } catch (RejectedExecutionException e) {
                System.out.println("第" + i + "次提交线程被拒绝!  当前活动线程数:" + executor.getActiveCount()
                    + " 队列长度:" + executor.getQueue().size());
            }
        }
    }
}

 运行的结果:

第8次提交线程被拒绝!  当前活动线程数:3 队列长度:5
第9次提交线程被拒绝!  当前活动线程数:3 队列长度:5
一月 21, 2015 9:11:03 下午 com.cathy.demo.concurrency.executor.threadFactory.MyAppThread run
信息: Created Test-2
一月 21, 2015 9:11:03 下午 com.cathy.demo.concurrency.executor.threadFactory.MyAppThread run
信息: Created Test-1
一月 21, 2015 9:11:03 下午 com.cathy.demo.concurrency.executor.threadFactory.MyAppThread run
信息: Created Test-3
一月 21, 2015 9:11:05 下午 com.cathy.demo.concurrency.executor.threadFactory.MyAppThread run
信息: Exiting Test-3
一月 21, 2015 9:11:05 下午 com.cathy.demo.concurrency.executor.threadFactory.MyAppThread run
信息: Exiting Test-1

DiscardPolicy 是抛弃当前任务

 


/**
 *
 * @author zhangwei_david
 * @version $Id: DiscardTestClient.java, v 0.1 2014年11月13日 下午3:16:28 zhangwei_david Exp $
 */
public class DiscardTestClient {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        final ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 2, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(5));

        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

        for (int i = 0; i < 10; i++) {
            System.out.println(MessageFormat.format("第{0}次提交任务,当前等待队列长度{1}", i, executor.getQueue()
                .size()));
            executor.execute(new Runnable() {

                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        //logger.error("", e);
                    }
                }
            });

        }
        executor.shutdown();

    }

}
 运行结果是:
第0次提交任务,当前等待队列长度0
第1次提交任务,当前等待队列长度0
pool-1-thread-1
第2次提交任务,当前等待队列长度1
第3次提交任务,当前等待队列长度2
第4次提交任务,当前等待队列长度3
第5次提交任务,当前等待队列长度4
第6次提交任务,当前等待队列长度5
pool-1-thread-2
第7次提交任务,当前等待队列长度5
pool-1-thread-3
第8次提交任务,当前等待队列长度5
第9次提交任务,当前等待队列长度5
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-1
pool-1-thread-3
 通过结果可以发现,提交了10个任务最终只有8个任务被执行!其中有两次被抛弃了!
DiscardOldestPolicy :抛弃最旧的任务

 

 

 

 

/**
 *
 * @author zhangwei_david
 * @version $Id: DiscardOldestTest.java, v 0.1 2015年1月22日 上午9:42:21 zhangwei_david Exp $
 */
public class DiscardOldestTest {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        final ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 2, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(5));

        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());

        for (int i = 0; i < 10; i++) {
            System.out.println(MessageFormat.format("第{0}次提交任务,当前等待队列长度{1}", i, executor.getQueue()
                .size()));
            executor.execute(new MyTask(String.valueOf(i)));

        }
        executor.shutdown();

    }

    public static class MyTask implements Runnable {

        private String name;

        /**
         * @see java.lang.Runnable#run()
         */
        public void run() {
            System.out.println(name);
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                //logger.error("", e);
            }
        }

        public MyTask(String name) {
            super();
            this.name = name;
        }

    }

}
 

 

 

 

第0次提交任务,当前等待队列长度0
0
第1次提交任务,当前等待队列长度0
第2次提交任务,当前等待队列长度1
第3次提交任务,当前等待队列长度2
第4次提交任务,当前等待队列长度3
第5次提交任务,当前等待队列长度4
第6次提交任务,当前等待队列长度5
第7次提交任务,当前等待队列长度5
第8次提交任务,当前等待队列长度5
第9次提交任务,当前等待队列长度5
6
7
3
4
5
8
9
 发现第二次和第三次提交的任务被抛弃了!

 

 

 

你可能感兴趣的:(Java 之ThreadPoolExecutor.RejectedExecutionHandler)