V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wholve
V2EX  ›  程序员

关于线程池的问题

  •  
  •   wholve · 2023-05-15 15:11:36 +08:00 · 1822 次点击
    这是一个创建于 560 天前的主题,其中的信息可能已经有所发展或是发生改变。

    线程池有个疑问,我的机器 4 核 16G,按照最优的线程数 2n+1 来说为 9 个,但是在如下代码中

    public static void main(String[] args) {
            // 创建线程池,500 个线程数
            ExecutorService es = ThreadUtils.getInstance("approveProcessForBatch", 500);
            Map<Integer, Future<Object>> futureMap = new HashMap<>(SystemConstant.INITIAL_CAPACITY);
            for (int i = 0; i <= 250; i++) {
                // delay5s 耗时 5s
                es.submit(() -> delay5s(""));
            }
            System.out.println("开始执行时间:" + DateTime.now());
            for (int i = 0; i <= 100; i++) {
                int finalI = i;
                Future<Object> future = es.submit(() -> delay5s("当前任务" + finalI));
                futureMap.put(finalI, future);
            }
            futureMap.keySet().forEach(i -> {
                try {
                    // v 是当前任务名称
                    Object v = futureMap.get(i).get();
                    System.out.println(v + ",完成时间:" + DateTime.now());
                } catch (ExecutionException | InterruptedException e) {
                    throw new BusinessException(e);
                }
            });
        }
    

    目前设置了 500 个线程数,会在 5s 之后将 100 个任务全部完成,假如我只设置 9 个,那预计需要 250/9 * 5s 的时间,导致这个现象的原因是啥?

    13 条回复    2023-05-17 18:12:06 +08:00
    blankmiss
        1
    blankmiss  
       2023-05-15 15:41:30 +08:00
    什么原因 你倒是说清楚啊
    mango88
        2
    mango88  
       2023-05-15 16:02:57 +08:00
    从你的描述看,ThreadUtils.getInstance 代码仅是设置了 corePoolSize
    不清楚你的这段代码是如何设置线程池其他几个参数的,maximumPoolSize ,workQueue 等
    如果是无界队列的话,队列满了才会去创建新的线程(线程数 > corePoolSize )直到线程数 = maximumPoolSize
    misdake
        3
    misdake  
       2023-05-15 16:04:14 +08:00
    delay5s 的实现能给么,你说“delay5s 耗时 5s”,是不是线程 sleep 而不是一直占用 cpu 。
    mango88
        4
    mango88  
       2023-05-15 16:05:10 +08:00
    @mango88 更正一下,如果是无界队列的话, => ~如果是无界队列的话,~
    hanstyle
        5
    hanstyle  
       2023-05-15 16:09:51 +08:00
    可能要看下 delay5s()方法是不是没占用 cpu 资源
    vagusss
        6
    vagusss  
       2023-05-15 16:30:10 +08:00
    线程数的设置主要还是看任务类型, cpu 密集型和其他类型比如 IO 密集型不能一概而论
    vagusss
        7
    vagusss  
       2023-05-15 16:31:50 +08:00
    google 一下有很多文章讲解, 我随便搜了一篇 https://juejin.cn/post/7072281409053786120
    notwaste
        8
    notwaste  
       2023-05-15 16:40:34 +08:00
    delay5s 如果是 Thread.sleep 的话会释放 CPU ,在一个线程 delay5s 的同时 CPU 会去执行其他线程的 delay5s
    oldshensheep
        9
    oldshensheep  
       2023-05-15 17:40:33 +08:00
    因为你线程都在 sleep ,啥都没干。
    不过 Java 的 Virtual Thread 正式在 JDK21 发布,就基本上没什么线程池的事了
    kirito41dd
        10
    kirito41dd  
       2023-05-15 19:18:04 +08:00
    @oldshensheep java8: 你说啥?(
    opengps
        11
    opengps  
       2023-05-15 23:35:45 +08:00 via Android
    线程的动态创建就是这么慢,一秒才一个
    WashFreshFresh
        12
    WashFreshFresh  
       2023-05-16 10:04:35 +08:00
    如果线程池是无界队列,coresize 和 maxsize 都是你给的线程数的话,就解释的通。每次都只能提交 9 个任务,然后卡住了,等 5s 后任务结束,线程都释放了,才能继续提交新的任务。
    wholve
        13
    wholve  
    OP
       2023-05-17 18:12:06 +08:00
    delay5s 这个方法我自定义的,模拟业务方法耗时,我直接 sleep 了 5s 确实没有占用 cpu;
    真实的业务方法,包含查询 sql,调用外部接口,以及业务代码,估计也是没有一直占用 cpu 资源导致的吧?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5596 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 08:00 · PVG 16:00 · LAX 00:00 · JFK 03:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.