new Thread() 的危害

一、危害

1)开销大

每次new Thread() 都会创建新的对象,开销较大,无法复用增加垃圾回收的负担。

2)管理困难

每个new Thread() 都是独立的个体,无法有效的管控,无限制创建相互竞争,可能导致oom或者核心业务线程阻塞。

3)功能单一

无法定时执行,中断线程等功能。

二、线程池

1)复用已创建的线程,减少对象创建、消亡的开销,性能佳。
2)可控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
3)可定时执行、中断线程等功能。

三、线程池大小

1)CPU密集型(计算型)

使用较小的线程池,一般是Cpu核心数+1
因为CPU密集型任务CPU的使用率很高,若开过多的线程,只能增加线程上下文的切换次数,带来额外的开销

2)IO密集型(查询访问型)

使用较大的线程池,一般CPU核心数 * 2
因为IO密集型CPU使用率不高,可以让CPU等待IO的时候处理别的任务,充分利用cpu时间

四、线程池创建

使用ThreadPoolExecutor手动创建。

public class CommonThreadPool {

    /**
     * 线程池对象
     */
    public static ExecutorService pool = null;
    /**
     * 线程池核心池的大小
     */
    private static final int CORE_POOL_SIZE = 5;
    /**
     * 获取当前系统的CPU 数目
     */
    private static int cpuNums = Runtime.getRuntime().availableProcessors();
    /**
     * 线程池的最大线程数
     */
    private static final int MAX_POOL_SIZE = (cpuNums * 2) > CORE_POOL_SIZE ? (cpuNums * 2) : CORE_POOL_SIZE;

    static {
        pool = new ThreadPoolExecutor(
                CORE_POOL_SIZE,             // 核心线程数
                MAX_POOL_SIZE,              // 最大线程数 通常核心线程数=最大线程数 当MAX_POOL_SIZE > CORE_POOL_SIZE 时,并不是当核心线程全部被占用后立马开始创建新的线程(只有在队列也满了之后才会开始新建线程)
                0L,            // 存活时间   >=0 0 永不回收【非核心线程除外】
                TimeUnit.MILLISECONDS,      // 单位
                new ArrayBlockingQueue<Runnable>(100),                          // 队列 存放待执行任务
                new ThreadFactoryBuilder().setNameFormat("CommonThread-%d").build(),    // 创建工厂
                new ThreadPoolExecutor.AbortPolicy());                                  // 拒绝策略 默认拒绝 丢弃 丢弃最老的 主线程执行
    }

}

五、禁用Executors创建线程池

1)Executors屏蔽的线程池的内部实现细节,开发人员需要根据服务器情况与业务场景定义更合适的线程池。

2)newFixedThreadPool 和 newSingleThreadExecutor的主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

3)newCachedThreadPool 和 newScheduledThreadPool:主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

LinkedBlockingQueue:队列默认大小Integer.MAX_VALUE,未指定大小时可以视为无界队列。

SynchronousQueue:队列大容量为0,不存储任何数据。

DelayedWorkQueue:无界,队列顺序按照延时时长排序。

六、任务执行流程

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值