当前位置:   article > 正文

记java生产项目中线程池使用的一点总结_java 管理多个线程池

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());
  • 1
  • 2
  • 3
  • 4

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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

本地异步队列

启动独立的线程,使用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);
                    }
                }
            });
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

线程参数配置

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

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

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

总结

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/1008783
推荐阅读
相关标签
  

闽ICP备14008679号