【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool
和 SingleThreadPool
: 允许的请求队列长度为 Integer.MAX_VALUE
,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool
: 允许的创建线程数量为Integer.MAX_VALUE
,可能会创建大量的线程,从而导致 OOM。
源码
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
创建newCacheThreadPool
线程池:
ExecutorService executorService = Executors.newCachedThreadPool();
Executors.newCachedThreadPool()
创建出来的newCachedThreadPool
实际上是创建一个ThreadPoolExecutor
(线程池执行器)类
ThreadPoolExecutor
参数说明:
其中,Interger.MAX_VALUE = 231 - 1,即线程池中核心线程为 0 个,非核心线程最大为 231 - 1(而不是初始化就有这么多),空闲的非核心线程生命周期为60s。任务队列为SynchronousQueue,这个队列是无法插入任务的,一有任务立即执行,所以newCachedThreadPool比较适合任务量大但耗时少的任务。
一旦有任务 ,newCachedThreadPool就会不断创建非核心线程来执行任务,执行任务结束的线程会重新回到线程池等待复用。
源码
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
创建newFixedThreadPool
线程池:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(n); // 参数核心n代表线程数量,也代表最大线程数量
newFixedThreadPool的核心线程数量和最大线程数量为传入的n
,也就是说非核心线程数量为 0
,非运行状态的非核心线程存活时间是0 ms
,任务队列是LinkedBlockingQueue(链表实现的有界队列,默认构造方法的队列长度是Integer.MXA_VALUE
)
newFixedThreadPool线程池执行任务时,如果线程池内存在空闲的核心线程,则用核心线程执行任务,如果核心线程都不空闲,此时还有任务产生,则将任务存储到LinkedBlockingQueue队列中,等待核心线程执行任务后,再从队列中取出任务执行
源码
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
创建newSingleThreadPool
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
newSingleThreadPool的核心线程数量和最大线程数量为传入的1
,也就是说非核心线程数量为 0
,非运行状态的非核心线程存活时间是0 ms
,任务队列是LinkedBlockingQueue(链表实现的有界队列,默认构造方法的队列长度是Integer.MXA_VALUE
)
newSingleThreadPool线程池执行任务时,只有唯一的核心线程在执行任务,核心线程执行任务结束,再从队列中取出任务执行
常用于需要延迟执行或周期循环执行任务的场景
源码
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }
threadFactory
:执行器创建新线程时使用的工或者
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
package com.zhan.threadPool; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Demo { public static void main(String[] args) { System.out.println("时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( new Date())); ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { try{ Thread.sleep(1000L); System.out.println("时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( new Date())); } catch (InterruptedException e) { e.printStackTrace(); } } }, 5, 2, TimeUnit.SECONDS); } }
设置任务时长大于执行周期
Thread.sleep(3000L);
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
scheduledThreadPool.schedule(new Runnable() { @Override public void run() { try{ //Thread.sleep(3000L); System.out.println("时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( new Date())); } catch (Exception e) { e.printStackTrace(); } } }, 2, TimeUnit.SECONDS); }
执行后线程不会结束
public <T> Future<T> submit(Runnable task, T result) { return schedule(Executors.callable(task, result), 0, NANOSECONDS); }
执行后将执行结果放入result,并作为返回值返回
提交优先级:核心线程池 > 队列 > 非核心线程池
执行优先级:核心线程池 > 非核心线程池 > 队列