用户工具


使用场景

  • 看中延迟,任务队列使用SynchronousQueue队列
    • 优点:每个任务提交后就能被执行,避免了在队列中等待的不可控时间
    • 缺点:生产者,消费者线程频繁对齐使吞吐量下降
  • 看中吞吐量,任务队列使用LinkedBlockingQueue
    • 优点:队列做一个缓存,减少生产者、消费者之间线程对齐的次数(增加吞吐量)
    • 缺点:在消费者遇到性能变差时。无法控制队列中的任务被执行的时间(可能很多任务会在队列中停留很久)

测试

  • 10个生产者线程,提交1000w个任务
  • 4个消费者线程
  • SynchronousQueue性能:平均每秒提交处理100w个task
  • LinkedBlockingQueue性能:平均每秒提交处理500w个task

现有线程池的缺点

  • submit(),提交任务的时间和执行任务的时间没有分离
    • 解决方案:自定义策略。任务提交时,设置超时时间(见下面代码)
  • invokeAll() + AbortPolicy策略,如果有一个任务提交失败,则整体失败
    • 解决方案:自定义策略。当任务提交失败时,将那个任务cancel掉,而不是抛出异常
  • invokeAll() + DiscardPolicy策略,如果有一个任务提交失败,则invokeAll需要等到超时时间。因为被抛弃的任务根本没有被执行
    • 解决方案:自定义策略。当任务提交失败时,将那个任务cancel掉
    static class MyPolicy implements RejectedExecutionHandler {

        private int submitTimeoutms;

        static RejectedExecutionException exp = new RejectedExecutionException();

        public MyPolicy(int submitTimeoutms) {
            this.submitTimeoutms = submitTimeoutms;
        }
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            try {
                // queue 指线程池中的任务队列
                boolean res = queue.offer(r, submitTimeoutms, TimeUnit.MILLISECONDS);
                if(!res){
                    ((FutureTask) r).cancel(true);
                    throw exp;
                }
            } catch (InterruptedException e1) {
                throw exp;
            }
        }
    }