【并发编程】Executor线程池框架-图文源码详解

目录

0 框架类图

1. Executors工具类

2 ThreadPoolExecutor 

2.1 API常用方法

2.1.1 构造方法

2.1.2 核心方法execute(Runnable r)

2.1.3 addWorker创建工作线程

2.2 组件解析

2.2.1 worker

2.2.2 ThreadFactory

2.2.3 BlockingQueue


0 框架类图

在这里插入图片描述

常用的Executors类是工具类,静态工厂方法(简单工厂模式),实际生产ThreadPoolExecutor。

ThreadPoolExecutor是核心实现类,下面来详细介绍

1. Executors工具类

API如下,常用几种种静态工厂方法newFixedThreadPool固定大小、newSingleThreadExecutor单线程、newCachedThreadPoolnewScheduledThreadPool固定时延(定时任务),实际生产出来的都是ThreadPoolExecutor

ThreadPoolExecutor

构造参数

newFixedThreadPool(n) newSingleThreadExecutor() newCachedThreadPool() newScheduledThreadPool(n)
corePoolSize n(方法参数) 1 0 n
maximumPoolSize n 1 Integer.MAX_VALUE Integer.MAX_VALUE
keepAliveTime 0 0 60 0
unit MILLISECONDS毫秒 MILLISECONDS毫秒 SECONDS秒 MILLISECONDS毫秒
workQueue LinkedBlockingQueue LinkedBlockingQueue SynchronousQueue DelayedWorkQueue
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
...
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}

2 ThreadPoolExecutor 

2.1 API常用方法

2.1.1 构造方法

有4个构造方法,最常用第一个,带5个参数,参数接受稍后详解,

剩余的就是多指明线程工厂和拒绝策略,线程工厂用与创建线程,而拒绝策略就是在提交任务数 > maxPoolSize+queueSize时拒绝线程。

第一个构造方法如下:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue);

ThreadPoolExecutor 是Executor的基本实现,构造参数如下,通过这些参数可以控制其大小等

参数 含义 图解
corePoolSize 线程池基本大小

maximumPoolSize 线程池最大大小

keepAliveTime

线程存活时间,

空间时间**>keepAliveTime

标记为可回收

unit

时间单位,

枚举可设置为秒、毫秒等

 
workQueue 工作队列类型

2.1.2 核心方法execute(Runnable r)

提交任务到线程池

2.1.3 addWorker创建工作线程

前置会判断当前的线程数量,此处省略了,当符合size条件符合(如上图展示),就会

new Worker实例(会使用线程工厂threadFactory创建一个以当前worker为Runnable参数的新线程),

然后一些状态判断,并加入到线程池ThreadPoolExecutor的workers集合,

最后启动线程start,调度后就能执行这个Worker的run方法。具体请见下面Worker章节~

2.2 组件解析

主要包含Worker、ThreadFactory、BlockingQueue

2.2.1 worker

就是工作线程,实现了Runnable,并持有Runnable

构造方法

Worker(Runnable firstTask) {
    setState(-1); // inhibit interrupts until runWorker
    this.firstTask = firstTask;
    this.thread = getThreadFactory().newThread(this);
}

run方法

主要是在while循环体中一直从任务队列中获取Runnable任务,直接调用其run方法,所以并不是提交多少次就会生产多少线程去执行任务的,工作线程是复用的,工作线程的run方法中循环调用任务的run方法而已。(命令模式)

    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // 允许中断
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) { // 首次任务||从队列获取任务workQueue.take();
                w.lock();
                // 如果线程池被置为stoping,中断线程 否则保证不中断
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    beforeExecute(wt, task);// 空实现
                    try {
                        task.run(); // 执行任务!!!
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);// 空实现
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly); // 空闲且非core则销毁worker
        }
    }

2.2.2 ThreadFactory

ThreadFactory是个接口,顾名思义就是用于生产线程的工厂,(简单工厂模式),我们通常不指定这个参数,所以会选用默认的实现。

默认实现DefaultThreadFactory是Executors的静态内部类,主要生产线程的方法非常简单,如下

public Thread newThread(Runnable r) {
    Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(),0);
    if (t.isDaemon())
        t.setDaemon(false); //非守护线程
    if (t.getPriority() != Thread.NORM_PRIORITY)
        t.setPriority(Thread.NORM_PRIORITY); //普通优先级
    return t;
}

2.2.3 BlockingQueue

通常的生产者/消费者模型会选择使用BlockingQueue,主要特性就是在空时取会阻塞,满时offer会阻塞,家族如下,

 
发布了118 篇原创文章 · 获赞 107 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sarafina527/article/details/104973571