美文网首页
线程池注意事项

线程池注意事项

作者: 修行者12138 | 来源:发表于2021-02-27 18:27 被阅读0次

    执行任务的时候,先使用corePoolSize范围内的线程,多出的任务放到阻塞队列,阻塞队列放满了,才会用maximumPoolSize范围内的线程。

    如果阻塞队列设置成无界,有OOM的风险。

    线程/线程池一定要起好名字,这样用jstack导出threaddump文件后,可以看出线程是在执行什么业务。

    慎用showdownNow(),会直接把业务线程停掉,可能对业务造成影响。

    自定义线程池,最好有固定的后缀,与框架的线程池区分开,这样jstack的时候可以grep 固定后缀,只看自定义线程的信息。

    ExecutorService executorService = new ThreadPoolExecutor(10, 20, 0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingDeque<>(10), factory, new ThreadPoolExecutor.AbortPolicy());
    

    线程池配置如上,如果有22个任务,第1-10个任务由核心线程跑,第11-20个任务放入阻塞队列,第21-22个任务由新建线程(或者释放cpu资源后的核心线程)跑,第21-22个任务的执行顺序,先于第11-20个任务。

    当运行中的线程数已达到最大线程数,且阻塞队列已满时,对于新的任务,有以下策略
    CallerRunsPolicy: 把新的任务交给main线程执行
    DiscardPolicy: 直接舍弃
    AbortPolicy: 抛异常,不影响其他线程的执行,该策略可能导致线程无法释放
    DiscardOldestPolicy: 舍弃最旧的任务

    public static void main(String[] args) throws Exception{
        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("test-thread-pool-%d").build();
        ExecutorService executorService = new ThreadPoolExecutor(10, 20, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(10), factory, new ThreadPoolExecutor.AbortPolicy());
    
        for (int i = 1; i <= 31; i++) {
            final int j = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ": " + j);
                }
            });
        }
    
        executorService.shutdown();
    }
    

    上述代码,线程无法正常释放,jstack导出的dump日志大量waiting on condition

    相关文章

      网友评论

          本文标题:线程池注意事项

          本文链接:https://www.haomeiwen.com/subject/izzgfltx.html