作用

1)可以根据具体的应用场景和系统的承受能力,手动或自动的设置工作线程的数量,减少资源的浪费,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)
2)减少了创建线程和销毁线程的次数,提高了线程的可复用性

框架图

  • Executors类
    图片说明

  • Executor子接口及其子接口ExecutorService、子类AbstractExecutorService、底层实现类ThreadPoolExecutor
    图片说明

线程池的创建与使用

1)先创建一个线程池,主要有以下四种方式

//一池1个工作线程,类似于一个银行有N个受理窗口
ExecutorService threadPool = Executors.newSingleThreadExecutor();
//一池5个工作线程,类似于一个银行有5个受理窗口
ExecutorService threadPool = Executors.newFixedThreadPool(5);
//一池N个工作线程,类似于一个银行有N个受理窗口
ExecutorService threadPool = Executors.newCachedThreadPool();
//创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);

2)调用线程池的execute()方法

public class MyThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        try {
            //模拟有20个顾客来银行办理业务,目前池子里有5个工作人员提供服务
            for (int i = 1; i <= 20; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");
                    try{ TimeUnit.SECONDS.sleep(3); } catch(InterruptedException e){ e.printStackTrace(); }
                });
                try{ TimeUnit.SECONDS.sleep(1); } catch(InterruptedException e){ e.printStackTrace(); }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}

工作机制

将任务派发给线程池时,会出现以下几种情况
1)核心线程池未满,创建一个新的线程执行任务。
2)如果核心线程池已满,工作队列未满,将线程存储在工作队列。
3)如果工作队列已满,线程数小于最大线程数就创建一个新线程处理任务。
4)如果超过大小线程数,按照拒绝策略来处理任务。

线程池7大参数

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        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;
    }

1)corePoolSize:指定了线程池中的线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去;
2)maximumPoolSize:指定了线程池中的最大线程数量,这个参数会根据你使用的workQueue任务队列的类型,决定线程池会开辟的最大线程数量;
3)keepAliveTime:当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁;
4)unit:keepAliveTime的单位
5)workQueue:任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种;
6)threadFactory:线程工厂,用于创建线程,一般用默认即可;
7)handler:拒绝策略;当任务太多来不及处理时,如何拒绝任务;

拒绝策略

图片说明

阿里巴巴开发手册对线程池的使用

图片说明

参考链接:https://blog.csdn.net/qq_31753145/article/details/50899119