三大方法
我们可以通过工具类Executors来创建线程池,一般用三个方法
方法一
public static void main(String[] args) {//创建只有一个线程的线程池ExecutorService threadPool = Executors.newSingleThreadExecutor();try {for (int i = 0; i < 10; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + " 正在执行中...");});}} catch (Exception e) {e.printStackTrace();} finally {//关闭线程池threadPool.shutdown();}}

可以看到线程池只有一个线程
方法二
public static void main(String[] args) {//创建固定线程数量的线程池ExecutorService threadPool = Executors.newFixedThreadPool(5);try {for (int i = 0; i < 10; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + " 正在执行中...");});}} catch (Exception e) {e.printStackTrace();} finally {//关闭线程池threadPool.shutdown();}}

方法三
public static void main(String[] args) {//创建线程数量可伸缩的的线程池,不过也会有最大数量,不可能无限大ExecutorService threadPool = Executors.newCachedThreadPool();try {for (int i = 0; i < 10; i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() + " 正在执行中...");});}} catch (Exception e) {e.printStackTrace();} finally {//关闭线程池threadPool.shutdown();}
七大参数
再阿里巴巴开发规范中,明确规定不能直接使用工具类Executors来创建线程池,而需要其底层的TreadPoolExecutor类来创建:
TreadPoolExecutor类构造器源码:
public static void main(String[] args) {public ThreadPoolExecutor(int corePoolSize, // 核心线程池大小int maximumPoolSize, // 最大线程池大小long keepAliveTime, // 超过规定时间没有人调用就会释放TimeUnit unit, // 超时单位BlockingQueue<Runnable> workQueue, // 阻塞队列ThreadFactory threadFactory, // 线程工厂:创建线程的,一般不用动RejectedExecutionHandler handle // 拒绝策略){if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException();this.acc = System.getSecurityManager() == null ? null : AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}}
关于使用TreadPoolExecutor创建线程池,通过一个银行排队办理业务的方式介绍这个类的几个参数

人相当于需要使用该线程池执行的任务数量;
corePoolSize相当于正常开启的窗口1和窗口2;
maximumPoolSize相当于全部窗口,只有当等候席满人且还有人来办理业务的时候开启;
workQueue则相当于座位1~6,即阻塞队列的容量是6;
handle则是当所有窗口满人,等待席也满人但是依然有人想进银行办理业务时的拒绝策略;
测试类:
public class ThreadPoolTest {public static void main(String[] args) {ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,5,6,TimeUnit.SECONDS,new ArrayBlockingQueue<>(6),//Executors工具类的默认线程工厂Executors.defaultThreadFactory(),//队列满了,抛出异常!new ThreadPoolExecutor.AbortPolicy());try {//x是未知数for (int i = 0; i < x; i++) {threadPool.execute(()->{System.out.println(Thread.currentThread().getName() + "正在执行中...");});}} catch (Exception e) {e.printStackTrace();} finally {//关闭线程池threadPool.shutdown();}}}
下面看几种情况
当x在(0,corePoolSize+workQueue.size=2+6=8]时:
这时候始终只有两条线程在执行任务(图为x=8情况)
当x在(corePoolSize+workQueue.size=2+6=8,maximumPoolSize+workQueue.size=5+6=11]:
这时候就出现3条及以上的线程开始执行任务了(图为x=11的情况)
当x在(maximumPoolSize+workQueue.size=5+6=11,m=大于11的数]:
这时候就开始执行拒绝策略了(图为x=12的情况)
四种拒绝策略
// 银行满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.AbortPolicy()
// 哪来的去哪里,比如:主线程调用的线程池执行的话就去主线程执行任务
new ThreadPoolExecutor.CallerRunsPolicy()
//队列满了,丢掉任务,但不会抛出异常
new ThreadPoolExecutor.DiscardPolicy()
//队列满了,尝试去和最早执行的任务竞争,也不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()
