Bootstrap

对于线程池的理解

线程池

线程池的目的

什么是线程池:

线程池的基本思想是一种对象池,在程序启动时就开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

线程池的好处:

1、能够在某些情况下动态的调整工作线程的数量

2、可以大量节省系统频繁的创建和销毁线程所需要的资源

3、提高响应速度

线程池的组成:

1、线程池管理器(ThreadPoolManager):

用于创建并管理线程池 包括创建线程,销毁线程池,添加任务

2、工作线程(WorkThread):

线程池中线程,在没有任务时处于等待状态,可以循环的执行任务

3、任务接口(Task):

每个任务必须实现的接口,以供工作线程调度任务的执行。它规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;

4、任务队列:用于存放没有处理的任务。提供一种缓冲机制。

如何创建一个线程池?

Java中提供了创建线程程池的一个类:Executor

创建时,一般使用它的子类即:ThreadPoolExector

在这里插入图片描述
在这里插入图片描述

线程池中的corePoolSize就是线程池中的核心线程数量,这几个核心线程,只是在没有用的时候,也不会被回收,maximumPoolSize就是线程池中可以容纳的最大线程的数量,而keepAliveTime,就是线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间,而util,就是计算这个时间的一个单位,workQueue,就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)。threadFactory,就是创建线程的线程工厂,最后一个handler,是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。

在这里插入图片描述

任务进来时,首先执行判断,判断核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,若果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。

handler的拒绝策略:

有四种:第一种AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满这是默认使用的拒绝策略

​ 第二种DisCardPolicy:不执行新任务,也不抛出异常

​ 第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行

​ 第四种CallerRunsPolicy:直接调用execute来执行当前任务

线程池的种类

四种常见的线程池:

CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于量大但小而轻的任务。

SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。

SingleThreadPool:只有一条线程来执行任务一个线程消亡会有一个新的线程代替,适用于有顺序的任务的应用场景适用于任务单一要求顺序的任务。

FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程适用于负载重

线程池的基本实现:

  1. 线程池接口类 ThreadPool

    ``

    import java.util.List;
    
    /**
     * Desc:线程池接口类
     */
    public interface ThreadPool {
    
        // 执行单个线程任务
        void execute(Runnable task);
    
        // 执行多个任务
        void execute(Runnable[] tasks);
    
        // 执行多个任务
        void execute(List<Runnable> tasks);
    
        // 返回已经执行的任务个数
        int getExecuteTaskNumber();
    
        // 返回等待被处理的任务个数,队列的长度
        int getWaitTaskNumber();
    
        // 返回正在工作的线程的个数
        int getWorkThreadNumber();
    
        // 关闭线程池
        void destroy();
    }
    
  2. 线程池实现类ThreadPoolManager.java

    ``

    import java.util.Arrays;
    import java.util.List;
    import java.util.Queue;
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.concurrent.atomic.AtomicLong;
    
    /**
     * Desc:线程池实现类
     */
    public class ThreadPoolManager implements ThreadPool {
    
        // 线程池中默认线程的个数为5
        private static Integer workerNum = 5;
    
        // 工作线程数组
        WorkThread[] workThreads;
    
        // 正在执行的线程任务数量
        private static volatile Integer executeTaskNumber = 0;
    
        // 任务队列, 作为一个缓冲
        private Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<>();
    
        // 单例模式
        private static ThreadPoolManager threadPool;
    
        private AtomicLong threadNum = new AtomicLong();
    
        private ThreadPoolManager() {
            this(ThreadPoolManager.workerNum);
        }
    
        private ThreadPoolManager(int workerNum) {
            if (workerNum > 0) {
                ThreadPoolManager.workerNum = workerNum;
            }
            workThreads = new WorkThread[ThreadPoolManager.workerNum];
            for (int i = 0; i < ThreadPoolManager.workerNum; i++) {
                workThreads[i] = new WorkThread();
                Thread thread = new Thread(workThreads[i], "ThreadPool-worker-" + threadNum.incrementAndGet());
                thread.start();
                System.out.println("初始化线程总数:" + (i+1) + ",当前线程名称是:ThreadPool-worker-" + threadNum);
            }
        }
    
        public static ThreadPool getThreadPool() {
            return getThreadPool(workerNum);
        }
    
        public static ThreadPool getThreadPool(int workerNum) {
            if (workerNum > 0) {
                ThreadPoolManager.workerNum = workerNum;
            }
            if (threadPool == null) {
                threadPool = new ThreadPoolManager(ThreadPoolManager.workerNum);
            }
            return threadPool;
        }
    
    
        @Override
        public void execute(Runnable task) {
            synchronized (taskQueue) {
                taskQueue.add(task);
                taskQueue.notifyAll();
            }
        }
    
        @Override
        public void execute(Runnable[] tasks) {
            execute(Arrays.asList(tasks));
        }
    
        @Override
        public void execute(List<Runnable> tasks) {
            synchronized (taskQueue) {
                for (Runnable task : tasks) {
                     taskQueue.add(task);
                }
                taskQueue.notifyAll();
            }
        }
    
        @Override
        public String toString() {
            return "ThreadPoolManager{" +
                    "当前的工作线程数量=" + getWorkThreadNumber() +
                    ", 已完成的任务数=" + getExecuteTaskNumber() +
                    ", 等待任务数=" + getWaitTaskNumber() +
                    '}';
        }
    
        @Override
        public int getExecuteTaskNumber() {
            return executeTaskNumber;
        }
    
        @Override
        public int getWaitTaskNumber() {
            return taskQueue.size();
        }
    
        @Override
        public int getWorkThreadNumber() {
            return workerNum;
        }
    
        @Override
        public void destroy() {
            while (!taskQueue.isEmpty()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < workThreads.length; i++) {
                workThreads[i].shutdown();
                workThreads[i] = null;
            }
            threadPool = null;
            taskQueue.clear();
        }
    
        private class WorkThread implements Runnable {
            // 线程是否可用
            private boolean isRunning = true;
    
            @Override
            public void run() {
                Runnable r = null;
                while (isRunning) {
                    // 队列同步机制,加锁
                    synchronized (taskQueue) {
                        while (isRunning && taskQueue.isEmpty()) {
                            try {
                                taskQueue.wait(20);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        if (!taskQueue.isEmpty()) {
                            r = taskQueue.poll();
                        }
                    }
                    if (r != null) {
                        r.run();
                    }
                    executeTaskNumber++ ;
                    r = null;
                }
            }
    
            public void shutdown() {
                isRunning = false;
            }
        }
    }
    
  3. 自定义任务类Task.java

    ``

    /**
     * Desc:自定义任务类
     */
    public class Task implements Runnable {
    
        private static volatile Integer i = 1;
    
        @Override
        public void run() {
            // 执行任务
            synchronized (i) {
                System.out.println("当前处理的线程是:" + Thread.currentThread().getName() + ",执行任务:" + (i++) + "完成");
            }
        }
    }
    
  4. 线程池测试类

    ``

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Desc:线程池测试类
     */
    public class ThreadPoolTest {
        public static void main(String[] args) {
            ThreadPool t = ThreadPoolManager.getThreadPool(6);
            List<Runnable> tasks = new ArrayList<>();
            for (int i = 0; i < 100; i++) {
                tasks.add(new Task());
            }
            System.out.println(t);
            t.execute(tasks);
            // 所有的线程执行完成才destroy
            t.destroy();
            System.out.println(t);
        }
    }
    

核心参数的意义

public ThreadPoolExecutor(int corePoolSize,

​ int maximumPoolSize, //可以容纳的最大线程的数量

​ long keepAliveTime, //非核心线程可以保留的空闲时间

​ TimeUnit unit, //计算空闲时间的单位

​ BlockingQueue workQueue, //等待队列

​ ThreadFactory threadFactory, //创建线程的线程工厂

​ RejectedExecutionHandler handler//拒绝策略,任务满了之后拒绝执行某些任务
)

核心方法讲解

AbstractExecutorService抽象类的基本属性

AbstractExecutorService是个抽象类主要是对ExecutorService接口方法的一些实现。

  private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 
 //这个状态位是来记录workerCount和runState的值,高三位是运行状态,低29位是workerCount的值
 
  private static final int COUNT_BITS = Integer.SIZE - 3; // 29
  private static final int CAPACITY   = (1 << COUNT_BITS) - 1; //容量 2^29 -1 
 
     // 表示线程池可以接受新的任务,并且处理阻塞队列当中的任务
    private static final int RUNNING    = -1 << COUNT_BITS;
    // 不接受新的任务,但是会去处理阻塞队列当中的任务
    private static final int SHUTDOWN   =  0 << COUNT_BITS; 
   
    // 不接受新的任务,不处理队列当中的任务,中止正在运行中的任务
    private static final int STOP       =  1 << COUNT_BITS; 
 
    // 所有的任务都中止了,workCount变为0,并且会去执行terminated方法
    private static final int TIDYING    =  2 << COUNT_BITS; 
 
 
    // 在TIDYING状态的基础上,执行完了terminated方法
    private static final int TERMINATED =  3 << COUNT_BITS; 
 
    private final BlockingQueue<Runnable> workQueue; // 阻塞队列
 
    private final ReentrantLock mainLock = new ReentrantLock(); 
 
 private final HashSet<Worker> workers = new HashSet<Worker>(); //存放执行的任务
 
 private final Condition termination = mainLock.newCondition(); //终止条件
 
//线程池执行过得最大线程数 
private int largestPoolSize; 
 
//已经完成的线程数
 private long completedTaskCount; 
 
//创建线程的线程工厂
private 

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;