记java生产项目中线程池使用的一点总结

背景

最近项目中有很多使用线程池进行处理的地方,同时也碰到了几个问题比如线程池的个数该怎么评估,线程程的该怎么具体去使用,结合项目和实际场景得到一些理解

使用多线程的三种方式

设定多线程数量

通过指定核心和最大线程数大于1的方式来执行多个线程任务
适用场景:线程任务无需区分顺序,只需要有资源执行即可

new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MINUTES, queue, new ThreadFactoryBuilder()
                .setNameFormat(threadKey)
                .setUncaughtExceptionHandler((t, e) -> log.error("handler error: ", Thread.currentThread().getName(), e))
                .build(), new DiscardPolicy());

Map管理多个线程池方式

使用map管理多个线程池
适用场景:适合任务需要顺序执行的场景,通过任务的唯一键进行hash获取对应的线程池对象

  public static final Map<String, ExecutorService> map= new ConcurrentHashMap<>();

   public static void execute(String key, Runnable runnable) {
        String threadKey = key;
        ExecutorService service = map.get(threadKey);
        if (service == null) {
            service = init(threadKey);
            tsReciveThreadMap.put(threadKey, service);
        }
        service.execute(runnable);
    }

本地异步队列

启动独立的线程,使用LinkedBlockingQueue循环等待接收消息

适用场景:适合批量等待处理一批数据的场景,循环等待一定时间,批量存储数据

public Map<String, BlockingQueue> queue = new HashMap<>();

public void init(ExecutorService executorService) {
        for (int i = 0; i < 5; i++) {
            LinkedBlockingQueue<T> blockingQueue = new LinkedBlockingQueue<>();
            String key = i;
            queue.put(key, blockingQueue);
            executorService.execute(() -> {
                while (true) {
                    try {
                        T take = blockingQueue.take();
                        Map<String, T> data = new HashMap<>();
                        data.put(take.getKey(), take);
                        long current = System.currentTimeMillis();
                        while (!blockingQueue.isEmpty() && data.size() < 100 && System.currentTimeMillis() - current < 1000) {
                            T take1 = blockingQueue.poll();
                            if (take1 != null) {
                                data.put(take1.getKey(), take1);
                            }
                        }
                        this.handleMessage(data);
                    } catch (Exception e) {
                        log.error("", e);
                    }
                }
            });
        }
    }

线程参数配置

网上有一个比较广传的线程数设定公式

CPU 密集型的程序 - 核心数 + 1
I/O 密集型的程序 - 核心数 * 2

但是我们在设定线程数的时候,应该根据当前任务的具体逻辑来判断而不是使用网上这种通用公式。
以下有几个自己在项目中的实际体验
1.关注我们提交任务给线程池的流入速率
2.关注我们线程任务执行的流出速率
3.结合处理速率设定队列的大小

总结

上面列出了在实际项目中使用的3种线程池的方式,使用线程池要结合业务场景以及

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值