使用Executor框架创建线程池

Executor框架

Executor类:在java.util.concurrent类中,是JDK并发包的核心类。

ThreadPoolExecutor: 线程池。

Excutors: 线程池工厂,通过Executor可以创建一个特定功能的线程池。

一)、Executor框架的类的关系

Executor, ExecutorService, AbstractExcutorService, ThreadPoolExecutor,Executors

Eecutor类:

接口,只有一个execute()方法:

public interface Executor {
    void execute(Runnable command);
}

ExecutorService extends Executor类:

接口,ExecutorService extends Executor,主要方法如下:

   //关闭线程池
   void shutdown();
   boolean isShutdown();
   List shutdownNow();
   boolean isTerminated();
    Future submit(Callable task);
   //提交线程任务,并返回执行结果
   Future submit(Runnable task);

AbstractExecutorService类:

abstract class AbstractExecutorService implements ExecutorService,主要实现submit()方法。

    public Future submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task, null);
       //内部还是调用了execute()
        execute(ftask);
        return ftask;
    }

ThreadPoolExecutor类:

class ThreadPoolExecutor extends AbstractExecutorService

二)、线程池的状态:

参考:https://blog.csdn.net/nobody_1/article/details/98335594

运行(RUNNING): 线程池接收新任务,并处理队列中的任务。

关机(SHUTDOWN): 线程池不接受新的任务,但接收队列的任务,调用

​ shutdown()后线程的状态。

停止(STOP): 线程池不接受新的任务,也不处理队列中的任务,并中断执行中

​ 的任务,调用shutdownNow()线程的状态。

清理(tidying): 线程池所有任务已经终止,workCount(当前线程个数)为0,过渡

​ 到清理状态的线程将运行terminated()的子方法 。

终止(terminated): terminate()方法结束后线程的状态。

    //线程池的容量11111111111111111111111111111: 29个1
   private static final int CAPACITY   = (1 << COUNT_BITS)      - 1; 
    //运行状态,-2^29,10000000000000000000000000000,1个1,29个0
    private static final int RUNNING    = -1 << COUNT_BITS;     // 关机状态 0
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    // 停止 2^29
    private static final int STOP       =  1 << COUNT_BITS;
     // 清理状态 2 * 2^29
    private static final int TIDYING    =  2 << COUNT_BITS;
     // 终止状态 3 * 2^29
    private static final int TERMINATED =  3 << COUNT_BITS;

注:使用线程的高三位代表线程的状态,使用低29位代表工作线程的个数。

三)、获取池状态

private static int runStateOf(int c){ 
  //获得高3位
  return c & ~ CAPACITY;
}

四)、获得工作线程数

private static int workerCountOf(int c){
    return c & Capacity;
}

五)、使用AtomicInteger变量来表示线程池状态和工作线程数量

//刚开始初始化时,线程的状态默认为RUNNING, 工作线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0))
    
//rs:运行状态(runState), wc:工作线程数 (workCount)
 private static int ctlOf(int rs, int wc) {
    return rs | wc; 
}

使用ctl可以获取线程状态和工作线程数

int c = ctl.get();

runStateOf(c): 获取运行状态

workerCountOf(c): 获取工作线程数

六)、线程池对象:ThreadPoolExecutor

1)、主要属性:

  
//线程池的锁
private final ReentrantLock mainLock = new ReentrantLock();

//线程池中重用线程对象
private final HashSet workers = new HashSet();

//最大线程个数
private int largestPoolSize;
//当线程超过最大核心线程数时的阻塞队列
private final BlockingQueue workQueue;

//实时监控线程池的状态和工作线程的个数
 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
 private static final int COUNT_BITS = Integer.SIZE - 3;
//线程池的容量
 private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

   //线程池的运行状态
    // runState is stored in the high-order bits
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

2)、构造方法:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue 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.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

3)、参数信息:

corePoolSize: 指定了线程池中的线程数量

maximumPoolSize: 指定线程池中的最大线程数量

KeepAliveTime: 超过corePoolSize后增加的线程的空闲时间,超过这个时间线程

​ 未使用,则销毁该线程。

unit: KeepAliveTime的单位

workQueue: 任务队列,被提交但尚未被执行的任务

threadFactory: 线程工厂,一般用于创建线程。

handle: 拒绝策略,当任务太多,来不及处理,如何拒绝任务。

七)、workeQueue:等待队列

1).SynchronousQueue:直接提交的队列

​ 特点: 没有容量,每一个插入操作都要等待一个相应的删除操作。

​ 作用:应用于new CacheThreadPool线程池的workerQueue队列,不保存任务,

​ 总 是将任务提交给线程执行,如果没有空闲的进程,则尝试创建新的线

​ 程,如果进程的数量达到最大值,则执行拒绝策略。

注: 一直创建新的线程,直至线程数到达maximumPoolSize,执行拒绝策略。

2).ArrayBlockingQueue: 有界队列

​ 特点:使用构造函数,指定队列的最大容量

public ArrayBlockingQueue(int capacity){
    
}

​ 作用:当有新的任务要执行时,如果线程池的实际线程数小于coreSize,则会优先

​ 创建新的线程,若大于corePoolSize,则会将新任务加入等待队列,若等

​ 待队已满,在总线程数不大于maximumPoolSize的前提下创建线程,当总

​ 线程 数超过maxmmumPoolSize时执行拒绝策略。

** 注:**当线程数小于coreSize时,创建新的线程,大于coreSize时,将任务加入

​ 等待 队列,直至等待队列加满,在总线程数不超过maximumPoolSize的前

​ 提下创建线程,否则,执行拒绝策略。

3).LinkedBlockingQueue: 无界队列

​ 特点:除非资源耗尽,否则无界队列不存在任务入队失败的情况。

​ 作用:系统有任务时,若总的线程数小于corePoolSize则创建新的线程,否则,

​ 则将线程添加至等待队列中,无界队列保持快速增长,直至耗尽系统内

​ 存。

​ ** 注:** 当线程数小于corePoolSize时,创建新的线程,大于corePoolSize时,将

​ 任务加入等待队列中,直至耗尽系统内存,线程的个数一直维护在

​ corePoolSize 。

4).PriorityBlockingQueue: 优先任务队列

​ 特点:控制任务的执行先后顺序,是一个特殊的无界队列

作用:根据任务自身的优先级先后执行

八)、handler,JDK内置的四种拒绝策略

1). AbortPolicy: 直接抛出异常,阻滞系统工作

2).CallerRunsPolicy: 在调用者线程中运行当前被丢弃任务

3).DiscardOledstPolicy: 丢弃最老的一个请求,即即将被执行的一个任务,并尝试

​ 再次提交当前任务。

4).DiscardPolicy: 丢弃无法处理的任务,不予任何处理。

注:若要自定义拒绝策略,实现RejecteExecutionHandler接口,实现

​ rejectedExecution方法。

九)、execute()方法

步骤:

1)、参数传递,得到一个任务对象

2)、判断

//Runnable command 当前要执行的线程任务
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        //获取定前线程池的状态
        int c = ctl.get();
        //判断当前主线程数量是否超过corePoolSize,如果不超过,则新建一个线程对象
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //将任务添加到等待队列中,若队列未满,添加。已满,执行拒绝策略
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
     //队列已满,执行拒绝策略回调
        else if (!addWorker(command, false))
            reject(command);
    }


//线程池中添加新的线程,并执行线程任务
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            //获取运行状态
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //如若当前处于关闭、清理、终止,任务队列不为空时返回false,因为,队列不为空,说明线程个数达到核心线程的个数,不能创建新的线程值,返回false
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                //获取当前的主线程数
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                //增加线程池的大小
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            //重新创建一个线程
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());

                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        //线程池中添加新线程
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    //执行线程任务
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

七)、Executors:线程池工厂

继承ThreadPoolExecutor,可以取得一个特定功能的线程池

构造方法:

注:所有的线程池的构造,其内部最终都是调用了ThreadPoolExecutor的构造方法

1)、newFixThreadPool(int nThread): 创建一个固定大小的线程池

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }

2)、newSingleThreadExecutor(): 返回一个只有一个线程的线程池

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }

3) 、new CacheThreadPool(): 返回一个可以根据实际情况调整线程数量的线程池

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }

4)、new SingleThreadSchaduleExecutor(): 返回一个ScheduleExecutor对象,

retry: 标记循环位置,在continur和break后面加retry表示循环直接跳出到retry标

​ 记处。

   public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

你可能感兴趣的:(使用Executor框架创建线程池)