首先是创建线程池的几种方式
newFiexedThreadPool(int Threads):创建固定数目线程的线程池
newCachedThreadPool():创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程
newSingleThreadExecutor()创建一个单线程化的Executor
newScheduledThreadPool(int corePoolSize)创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类
注意!!!一般不会直接采用上面这几种方式去创建线程池
也就是这样
ExecutorService executor = Executors.newFixedThreadPool(10);
为什么??因为阿里巴巴说这样不好,它提示我了,为什么他说不行就是不行?为此百度了很多文章,最终看到这个解释
因为,使用Executors创建线程池可能会导致OOM(OutOfMemory ,内存溢出)
看一下ExecutorService newFixedThreadPool()底层源码
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
Java中的BlockingQueue主要有两种实现,分别是ArrayBlockingQueue 和 LinkedBlockingQueue。
ArrayBlockingQueue是一个用数组实现的有界阻塞队列,必须设置容量。
LinkedBlockingQueue是一个用链表实现的有界阻塞队列,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE。
这里的问题就出在:不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE。也就是说,如果我们不设置LinkedBlockingQueue的容量的话,其默认容量将会是Integer.MAX_VALUE。
而newFixedThreadPool中创建LinkedBlockingQueue时,并未指定容量。此时,LinkedBlockingQueue就是一个无边界队列,对于一个无边界队列来说,是可以不断的向队列中加入任务的,这种情况下就有可能因为任务过多而导致内存溢出问题。
上面提到的问题主要体现在newFixedThreadPool和newSingleThreadExecutor两个工厂方法上,并不是说newCachedThreadPool和newScheduledThreadPool这两个方法就安全了,这两种方式创建的最大线程数可能是Integer.MAX_VALUE,而创建这么多线程,必然就有可能导致OOM
FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为
Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
正确的使用应该是下面这段代码,注意,这是我现在知道的
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("我的线程池").build();
Examller myExercises1 = new Examller();
Examller myExercises2 = new Examller();
ExecutorService exec = new ThreadPoolExecutor(10,
10,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(10),namedThreadFactory);
exec.submit(myExercises2::B);
exec.submit(myExercises1::A);
看一下这个实现类的参数。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
1 corePoolSize int 核心线程池大小
2 maximumPoolSize int 最大线程池大小
3 keepAliveTime long 线程最大空闲时间
4 unit TimeUnit 时间单位
5 workQueue BlockingQueue 线程等待队列
6 threadFactory ThreadFactory 线程创建工厂
7 handler RejectedExecutionHandler 拒绝策略
其中有 :TimeUnit 这个里面
TimeUnit.DAYS //天
TimeUnit.HOURS //小时
TimeUnit.MINUTES //分钟
TimeUnit.SECONDS //秒
TimeUnit.MILLISECONDS //毫秒