为什么创建线程池不让用Executors?源码详解版

因为这样会导致内存不够用,内存耗尽,从而出现了OOM问题,所以阿里的java手册不建议使用Executors,建议使用ThreadPoolExecutor,这样创建就更加透明,而且让人更加熟悉线程池的过程,避免了创建大量的线程从而导致oom现象
错误代码演示:

package com.fan.mianshi100;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

public class Executor {
    public static void main(String[] args) {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
       // ThreadPoolExecutor

    }
}

1.先看第一个newFixedThreadPool()的源码:

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

根据我一开始写的程序,我只是限制了核心线程数,但是没有限制最大线程数,那么加之其使用的是无界队列 LinkedBlockingQueue,(其实这个也可以变为有界队列,只要给其参数,但是这个没给参数就是无界队列),那么程序就会创建无数的线程,从而使得内存不够用了,导致OOM问题

2.第二个是newSingleThreadExecutor的源码:

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

这个跟第一个一样,也是使用了无界队列:LinkedBlockingQueue

3.第三个是newCachedThreadPool()的源码:

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

这个是因为其线程最大设置为了Integer.MAX_VALUE,其最大值是 2,147,483,647,也就是2的32次方减1,这个数太大了,这么多的线程不发生OOM就怪事了

4.第四个是newScheduledThreadPool的源码:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

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

这个的问题也是将最大线程数设置成了Integer的最大数

5.第五个是newSingleThreadScheduledExecutor()的源码:

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }
 public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

跟第四个的最终引用源码都一样,也都是将最大线程数设置成了Integer的最大数

正确应该使用ThreadPoolExecutor来通过线程池来创建线程,这样可以开发者控制线程池的参数,同时也让开发者更加熟悉线程池了
代码演示:

package com.fan.mianshi100;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

//通过ThreadPoolExecutor来创建自定义的线程池
public class ThreadPoolExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,//核心线程数
                18,//最大线程数
                1,//非核心线程空闲存活时间
                TimeUnit.MINUTES,//上一个的时间单位
                new ArrayBlockingQueue<>(100));//任务队列,设置了容量了,
// 就不会存在无界队列,也不会产生oom问题了

        //将任务提交到线程池
        for (int i = 0; i < 20; i++) {
            int   taskNumber=i;
            executor.execute(()->{
                System.out.println("任务数"+taskNumber);
                try {
                    Thread.sleep(3000);  //模拟任务执行
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
        }
        //关闭线程池,如果我已经提交关闭线程池了,如果还有线程在执行
        //如果60秒之内无论是否执行完成,都会关闭线程池,这是一种激进的关闭,看情况了
        //具体情况具体分析
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60,TimeUnit.SECONDS)){
                executor.shutdown();
            }
        } catch (InterruptedException e) {
            executor.shutdown();
            throw new RuntimeException(e);
        }

        System.out.println("所有任务结束!");
    }
}

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值