创建新线程,需要和操作系统进行交互,成本比较高。
一、基础概念

KeepAliveTime:是多余的线程等待新任务的最长时间,超过这个时间多余的线程将被终止
workQueue:任务存储队列。
3种常见的队列:1. 直接交接 SynchronousQueue。SynchronousQueue的capacity是0,即不存储任何元素。2. 无界队列 LinkedBlockingQueue。3. 无界队列 ArrayBlockingQueue
threadFactory: 指定创建线程的工厂,一般不用指定,用默认的defaultThreadFactory即可。
二、几种线程池结构
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}
即核心线程数和最大线程数保持一致,因为是固定线程数,所以即使是线程空闲状态也不进行回收,所以KeepAliveTime也为0,任务队列采用LinkedBlockingQueue无界队列,因为当线程数超过最大线程数以后,需要将所有新增的线程放到无界队列里。
OOM异常原因:线程不断新增并且阻塞,导致无界队列占用内存超过锁分配的内存。
实现:
public class FixedThreadPool {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());for (int i = 0; i < 100; i++) {threadPoolExecutor.execute(new MyRunnable());}}static class MyRunnable implements Runnable {@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println("当前线程名:" + name);}}}
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());}
缓存线程池的核心线程数为0,最大线程数Integer.MAX_VALUE,即可以理解可以不断创建新的线程,任务队列使用SynchronousQueue,SynchronousQueue的容量为0,即不存线程.
OOM原因:每个线程任务都要新增一个线程,每个线程都要占用内存资源,一定数量导致OOM。
ScheduledThreadPoolExecutor
public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}
ScheduledThreadPoolExecutor主要用来在给定的延迟之后运 行任务,或者定期执行任务。由于队列使用的是DelayQueue是一个无界队列,所以这里的最大线程数maximumPoolSize没有什么意义。
实现:
public class ScheduledThreadPoolTest {public static void main(String[] args) {System.out.println("开始执行!");ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);//1.延迟5秒钟执行//scheduledExecutorService.schedule(new MyRunnable(),5, TimeUnit.SECONDS);//2.初始延迟3秒钟开始执行,每5秒钟执行一次scheduledExecutorService.scheduleAtFixedRate(new MyRunnable(),3,5,TimeUnit.SECONDS);}static class MyRunnable implements Runnable {@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println("当前线程名:" + name);}}}
三、停止线程池的方法
void shutdown();boolean isShutdown();List<Runnable> shutdownNow();boolean isTerminated();boolean awaitTermination(long timeout, TimeUnit unit);
shutdown()
public class ShutDownTest {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());for (int i = 0; i < 1000; i++) {threadPoolExecutor.execute(new MyTask());}threadPoolExecutor.shutdown();threadPoolExecutor.execute(new MyTask());}static class MyTask implements Runnable{@Overridepublic void run() {try {Thread.sleep(5000);System.out.println(Thread.currentThread().getName());} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName() + "被中断了");}}}}

当执行了shutdown方法,1000个线程有995个在队列里,队列里的任务仍然会执行,只是不能再执行新的线程。
isShutdown()
//当执行了shutdown方法以后,可以通过该方法判断线程池是否停止。executorService.isShutdown()
isTerminated()
boolean flag=executorService.isTerminated()
isTerminated()与isShutdown()方法的区别在于:isShutdown()只要执行了shutdown()方法,就会返回true,而isTerminated()方法需要等延迟队列里所有的任务执行完成才会返回true。
awaitTermination()
boolean b = executorService.awaitTermination(7L, TimeUnit.SECONDS);
上述代码表示7秒钟之内,判断线程池是否仍有未执行完成的线程。
shutdownNow()
public class ShutdownNowTest {public static void main(String[] args) throws InterruptedException {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());for (int i = 0; i < 1000; i++) {threadPoolExecutor.execute(new MyTask());}Thread.sleep(1500);List<Runnable> runnables = threadPoolExecutor.shutdownNow();}static class MyTask implements Runnable{@Overridepublic void run() {try {Thread.sleep(500);System.out.println(Thread.currentThread().getName());} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName() + "被中断了");}}}}//结果如下:pool-1-thread-5pool-1-thread-3pool-1-thread-4pool-1-thread-2pool-1-thread-5pool-1-thread-1pool-1-thread-3pool-1-thread-4被中断了pool-1-thread-5被中断了pool-1-thread-1被中断了pool-1-thread-3被中断了pool-1-thread-2被中断
可以看到,正在执行的核心线程立即都被中断了,同时,该方法返回队列里所有未执行的线程,这样可以将未执行的进行日志记录等等。
