• undifined
    2019-04-18
    思考题:
    1. 给线程池设置名称前缀
    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    threadPoolTaskExecutor.setThreadNamePrefix("CUSTOM_NAME_PREFIX");

    2. 在ThreadFactory中自定义名称前缀
    class CustomThreadFactory implements ThreadFactory {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread("CUSTOM_NAME_PREFIX");
                return thread;
            }
        }

    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,
                    100,
                    120,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(),
                    new CustomThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy()
            );
    展开
     1
     47
  • Seven Blue
    2019-04-22
    回答下Lrwin和张天屹同学的问题:当线程池中无可用线程,且阻塞队列已满,那么此时就会触发拒绝策略。对于采用何种策略,具体要看执行的任务重要程度。如果是一些不重要任务,可以选择直接丢弃。但是如果为重要任务,可以采用降级处理,例如将任务信息插入数据库或者消息队列,启用一个专门用作补偿的线程池去进行补偿。所谓降级就是在服务无法正常提供功能的情况下,采取的补救措施。具体采用何种降级手段,这也是要看具体场景。技术的世界里没有一尘不变的方案。另外,看到很多同学都提到让老师多讲讲源码,其实我觉得真没必要,老师目前的思路起到提纲契领的作用,让我们有大的思路,有全局观,具体细节我觉得大家私下去研究更合适。小弟不才,可以加微信(SevenBlue)一起讨论。

    作者回复: 👍我觉得那些源码用的时候看一下就可以了,现在都是用开源项目,天天都得看源码,看源码能局部最优而已

     1
     39
  • 榣山樵客™
    2019-04-18
    guava的ThreadFactoryBuilder.setNameFormat可以指定一个前缀,使用%d表示序号;
    或者自己实现ThreadFactory并制定给线程池,在实现的ThreadFactory中设定计数和调用Thread.setName

    作者回复: 👍

     1
     10
  • 张天屹
    2019-04-18
    老师你好,使用有界队列虽然避免了OOM 但是如果请求量太大,我又不想丢弃和异常的情况下一般怎么实践呢。我对降级这一块没经验,我能直观想到的就是存放在缓存,如果缓存内存也不够了就只能持久化了

    作者回复: 可以放数据库,放mq,redis,本地文件都可以,具体要看实际需求

    
     9
  • 随风🐿
    2019-04-29
    老师,有个问题一直不是很明确,①一个项目中如果多个业务需要用到线程池,是定义一个公共的线程池比较好,还是按照业务定义各自不同的线程池?②如果定义一个公共的线程池那里面的线程数的理论值应该是按照老师前面章节讲的去计算吗?还是按照如果有多少个业务就分别去计算他们各自创建线程池线程数的加和?③如果不同的业务各自定义不同的线程池,那线程数的理论值也是按照前面的去计算吗?

    作者回复: 建议不同类别的业务用不同的线程池,至于线程池的数量,各自计算各自的,然后去做压测。虽然你的系统有多个线程池,但是并不是所有的线程池里的线程都是忙碌的,你只需要针对有性能瓶颈的业务优化就可以了。

     1
     8
  • 海鸿
    2019-04-18
    1.利用guava的ThreadFactoryBuilder
    2.自己实现ThreadFactory

    作者回复: 👍

    
     8
  • 任大鹏
    2019-04-18
    老师的文中已经给出了一个答案:
    threadFactory:通过这个参数你可以自定义如何创建线程,例如你可以给线程指定一个有意义的名字。
    
     8
  • Red Cape
    2019-04-22
    请问老师,有界队列的长度怎么确定呢

    作者回复: 看场景,拍脑门

    
     7
  • linqw
    2019-06-19
    最近打算分析下Executor系列源码,先分析了下FutureTask源码,https://juejin.im/post/5d08be8ce51d455d6c0ad925,老师有空帮忙看下哦

    作者回复: 👍

    
     3
  • 曾轼麟
    2019-04-21
    public class ReNameThreadFactory implements ThreadFactory {
        /**
         * 线程池编号(static修饰)(容器里面所有线程池的数量)
         */
        private static final AtomicInteger POOLNUMBER = new AtomicInteger(1);

        /**
         * 线程编号(当前线程池线程的数量)
         */
        private final AtomicInteger threadNumber = new AtomicInteger(1);

        /**
         * 线程组
         */
        private final ThreadGroup group;

        /**
         * 业务名称前缀
         */
        private final String namePrefix;


        /**
         * 重写线程名称(获取线程池编号,线程编号,线程组)
         *
         * @param prefix 你需要指定的业务名称
         */
        public ReNameThreadFactory(@NonNull String prefix) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            //组装线程前缀
            namePrefix = prefix + "-poolNumber:" + POOLNUMBER.getAndIncrement() + "-threadNumber:";
        }


        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                    //方便dump的时候排查(重写线程名称)
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }
    展开

    作者回复: 👍

    
     3
  • 晓杰
    2019-04-19
    希望老师把线程异常处理这块可以再深入讲一讲
    
     3
  • 朱晋君
    2019-04-18
    我们项目中用了guava的new ThreadFactoryBuilder().setNameFormat()

    老师,请教个问题,在工程中,线程池的定义一般是在全局还是局部呢?如果全局的话,是不用shutdown吗?不关闭线程池有没有问题呢?

    作者回复: 一般都全局,如果需要优雅退出就需要shutdown。不关闭,会有coresize个线程一直回收不了。

    
     3
  • Kǎfκã²⁰²⁰
    2019-04-18
    线程命名常用方法是:线程的构造函数传入名字,或者调用setName设置
    
     3
  • magict4
    2019-04-18
    老师您好,请问有什么推荐的替代 Executors 的方案吗?

    作者回复: 我也没用其他的

    
     2
  • 郑晨Cc
    2019-04-18
    可参照SDK中的 DefaultThreadFactory 自定义DYIThreadFactory
    static class DIYThreadFactory implements ThreadFactory {
            private static final AtomicInteger poolNumber = new AtomicInteger(1);
            private final ThreadGroup group;
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final String namePrefix;

            DIYThreadFactory(String diyName) {
                SecurityManager s = System.getSecurityManager();
                group = (s != null) ? s.getThreadGroup() :
                                      Thread.currentThread().getThreadGroup();
                namePrefix = diyName +
                             "-thread-";
            }

            public Thread newThread(Runnable r) {
                Thread t = new Thread(group, r,
                                      namePrefix + threadNumber.getAndIncrement(),
                                      0);
                if (t.isDaemon())
                    t.setDaemon(false);
                if (t.getPriority() != Thread.NORM_PRIORITY)
                    t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }
        
        ExecutorService executor = Executors.newFixedThreadPool(4,new DIYThreadFactory("xxx"));
    展开

    作者回复: 👍

    
     2
  • 三年过后
    2020-01-31
    参考JDK 源码:DefaultThreadFactory
    
     1
  • Monday
    2020-01-04
    老师和同学们好,
    自定义拒绝策略中默认实现方法的是runnable对象和线程池两个参数,
    1、为什么不把submit进去的对象直接返回到拒绝策略?
    2、有没有优雅的方式获取拒绝任务中的业务数据,目前只能通过反射的方式来获取
    
     1
  • 随风而逝
    2019-05-05
    老师,这里的线程池,和Disruptor是一样的吗?

    作者回复: 不一样,线程池简单多了

    
     1
  • gogo
    2019-04-22
    老师,有一个问题想问一下:

    如果corePoolSize为10,maxinumPoolSize为20,而此时线程池中有15个线程在运行,过了一段时间后,其中有3个线程处于等待状态的时间超过keepAliveTime指定的时间,则结束这3个线程,此时线程池中则还有12个线程正在运行;若有六个线程处于等待状态的时间超过keepAliveTime指定的时间,则只会结束5个线程,此时线程池中则还有10个线程,即核心线程数。

    是这样吗?
    展开

    作者回复: 是的

    
     1
  • 密码123456
    2019-04-19
    有个问题,不能理解。既然execute使用newfixedthreadpool设置固定的线程池。在实际使用execute执行并发任务,cpu利用率会过高。按照道理说,只有开始的时候,线程会创建消耗资源。在创建之后都不会消耗资源才对啊?
    
     1
我们在线,来聊聊吧