关于dubbo使用过程中抛出【java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED!】的思考

说起这个异常那得追溯到十几个月以前的初夏的夜晚!~

作为有志青年此时虽已是深夜我们依然为系统拆分奋斗着。

xx同事正在压测。我目不转睛的盯着订单号服务的日志,忽然,java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED! 蹦了粗来。果断ctrl+c,由于当时对dubbo使用不深,也没有研究过源码,所以是一头雾水,百思不得骑姐。

后来硬着头皮看了下源码,于是乎~

了解到dubbo内部核心线程池:

以fixThreadPool举栗子:

public class FixedThreadPool implements ThreadPool {

    public Executor getExecutor(URL url) {
        String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
        int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
        int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
        return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, 
              queues == 0 ? new SynchronousQueue<Runnable>() : 
                 (queues < 0 ? new LinkedBlockingQueue<Runnable>() 
                       : new LinkedBlockingQueue<Runnable>(queues)),
              new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
    }

}
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    String msg = String.format("Thread pool is EXHAUSTED!" +
            " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
            " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!" ,
            threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),
            e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),
            url.getProtocol(), url.getIp(), url.getPort());
    logger.warn(msg);
    throw new RejectedExecutionException(msg);
}

在创建核心线程池的时候有个queues的参数,通过他来判断使用SynchronousQueue还是LinkedBlockingQueue,关于这二位区别java doc已做说明不再做赘述。
于是,之前在生产商看到的异常很容易就复现出来:
public class DubboTest {
    private static final Logger LOGGER= LoggerFactory.getLogger(DubboTest.class);

    public static void testUpdate() {
        URL url = new URL("Dubbo", "localhost", 9003);
        ExecutorService executor1 = new ThreadPoolExecutor(200, 20000, 60L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue(300),
//                        new SynchronousQueue(),  dubbo缺省使用这个workQueue
                new NamedThreadFactory("Dubbo", true),
                new AbortPolicyWithReport("dubbo", url));

        for (int i = 0; i < 50000000; i++) {
//                    System.out.println("----------"+i);
            executor1.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("heieieiei");
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----doing.....");
                }
            });
//                    System.out.println("###########"+i);
        }
    }

}
当然通过配置queue来解决线程池溢出的问题仅仅是缓兵之计,还是要从根源上优化底层逻辑,比如底层sql.


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值