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

请教下线程池提交线程池的写法

  •  
  •   rqxiao · 2022-11-29 15:22:45 +08:00 · 2312 次点击
    这是一个创建于 732 天前的主题,其中的信息可能已经有所发展或是发生改变。
        private static ThreadPoolExecutor getThreadPoolExecutor() {
            int corePoolSize=10;
            int maximumPoolSize=10;
            long keepAliveTime=1000L;
            BlockingQueue<Runnable> workQueue=new LinkedBlockingDeque<>(100);
            ThreadPoolExecutor threadPoolExecutor =  new ThreadPoolExecutor(
                    corePoolSize,
                    maximumPoolSize,
                    keepAliveTime,
                    TimeUnit.MILLISECONDS,
                    workQueue,
                    new ThreadPoolExecutor.CallerRunsPolicy()
                    );
            return threadPoolExecutor;
        }
    

    如下种写法常用吗,判断 ActiveCount 来提交线程

    
    #1
    
    int canCreateThreads = threadPool.getCorePoolSize()- threadPool.getActiveCount();
    log.info(" 支持核心线程数 : {} 个, 已激活 {} 个线程, 还可创建线程数 : {} 个", threadPool.getCorePoolSize(), threadPool.getActiveCount(),canCreateThreads);
    if (canCreateThreads > 0) {
     executor .execute(new Runnable(){})
    }
    
    
    
    

    之前工作中一直使用这种简单的方式,有任务时,直接提交线程池,具体怎么执行根据线程池配置来。

    #2
    
    executor.execute(new Runnable(){})
    
    
    17 条回复    2022-11-29 18:51:01 +08:00
    shazi199
        1
    shazi199  
       2022-11-29 15:29:19 +08:00
    应该可以设置拒绝策略吧,没必要再去判断了
    ipwx
        3
    ipwx  
       2022-11-29 15:33:00 +08:00   ❤️ 1
    难道 canCreateThreads <= 0 就把任务扔了么。。。流控也不应该依赖 threadPool 的具体实现来做吧,这思路清奇。
    urzz
        4
    urzz  
       2022-11-29 15:35:15 +08:00
    用这个判断的话,那还需要 workQueue 干嘛。。。
    出于啥考虑要用这个方式啊,这个思路着实看不懂
    rqxiao
        5
    rqxiao  
    OP
       2022-11-29 15:41:37 +08:00
    额 。还有补充一点#1 里 runnable 的 run 方法 最后还会有一段这样的代码,每次执行完一个线程的逻辑之后,还给他 interrupt()一下,然后自抛自捕。


    ```
    finally {

    logger.debug("{} 队列消费,标志线程为中断", Thread.currentThread().getName());
    Thread.currentThread().interrupt();
    throw new InterruptedException(
    Thread.currentThread().getName() + ".run() interrupted : 执行完毕");
    }
    } catch (InterruptedException e) {
    if (e.getMessage().endsWith(SysConstants.FINISH_INTERRUPTED)) {
    logger.debug(e.getMessage());
    } else {
    logger.error(e.getMessage());
    }
    }
    ```
    rqxiao
        6
    rqxiao  
    OP
       2022-11-29 15:43:10 +08:00
    @rqxiao 这个代码也不是很明白
    chendy
        7
    chendy  
       2022-11-29 15:44:11 +08:00
    @rqxiao 看麻了,直接结束不就完事了么……
    rqxiao
        8
    rqxiao  
    OP
       2022-11-29 15:45:48 +08:00
    @urzz
    目前是这样的代码。但使用起来还没发生过
    else{
    logger.error(" 已达到本应用处理上限,请稍后再试");
    //TODO 发送消息通知
    }
    loveaeen
        9
    loveaeen  
       2022-11-29 16:27:40 +08:00
    使用线程池的优势就是其本身可以维护内部线程的中断与创建,不需要我们来管这东西。想拒绝线程可以设置 BlockQueue 和 rejectPolicy 来解决。
    如果你们非要想自己创建指定数量线程并且想在线程内随意中止,那么不如采用 AtomicInteger 之类的全手动增删。
    建议多看看 2 楼文档
    urzz
        10
    urzz  
       2022-11-29 16:37:49 +08:00
    @rqxiao 那还真是用线程池来实现流控啊,惊了个呆

    手动 interrupt 是没有什么意义的,因为线程池本身会去做这些事。。建议看看 2 楼的文档+1
    rqxiao
        11
    rqxiao  
    OP
       2022-11-29 16:40:06 +08:00
    总体的代码 ![ ]( https://imgur.com/a/oSc4eVD)
    wetalk
        12
    wetalk  
       2022-11-29 16:41:50 +08:00
    你的写法极少见,其次,getActiveCount()方法的注释有个单词,approximate ,近似的。

    [Returns the approximate number of threads that are actively executing tasks.]
    rqxiao
        13
    rqxiao  
    OP
       2022-11-29 16:43:47 +08:00
    Jooooooooo
        14
    Jooooooooo  
       2022-11-29 16:44:07 +08:00
    直接提交即可

    你应该把拒绝策略放到线程池里做, 线程池不就干这个的吗?
    X0ray
        15
    X0ray  
       2022-11-29 16:50:18 +08:00
    你这样还不如在外层加一个 Semaphore ,通过信号量的数量来控制提交和写日志
    theniupa
        16
    theniupa  
       2022-11-29 17:41:46 +08:00   ❤️ 1
    你还不如用一个 ArrayBlockingQueue 指定一个长度,在 RejectPolicy 里面拿到这个 work-queue,在满任务 put 阻塞一下..
    clickhouse
        17
    clickhouse  
       2022-11-29 18:51:01 +08:00
    workQueue 已经设置队列了,new ThreadPoolExecutor.CallerRunsPolicy() 也已经设置拒绝策略了,用线程池就是希望自动管理,所以你只管提交就可以了。如果你觉得实际与期望不符,那么你应该去修改新建线程池的参数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2590 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 06:12 · PVG 14:12 · LAX 22:12 · JFK 01:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.