线程池(ThreadPool)使用和原理

房东的猫 提交于 2020-03-16 12:40:52

        通常我们构建线程池一般使用这种方式     ExecutorService executorService = Executors.newFixedThreadPool(4);//固定线程池

      但是阿里开发手册上面建议使用以下方式
      ThreadPoolExecutor(int corePoolSize,                                         //核心线程池                                       int maximumPoolSize,                                //最大线程池                                       long keepAliveTime,                                   //超时时间                                       TimeUnit unit,                                             //时间单位                                       BlockingQueue<Runnable> workQueue,  //队列                                       ThreadFactory threadFactory,                    //线程工厂                                       RejectedExecutionHandler handler)          //拒绝策略
      其实两种构建线程池的方式并没有什么本质的区别,阿里推荐的方式只是为了让线程池构建清楚的知道线程池的参数,避免过度内存开销和浪费   线程池五种状态
      下面我们就分析下线程池工作的流程
      executorService.execute(new Thread());
      executorService.shutdown();
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    //如果工作线程数小于核心线程数,新建一个核心线程执行任务
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
     ////2.核心池已满,但任务队列未满,添加到队列中
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        //再次检查线程池的状态,移除队列,拒绝任务reject
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            //新建线程
            addWorker(null, false);
    }
    //核心池已满,队列已满,试着创建一个新线程(最大线程数-核心线程数)
    else if (!addWorker(command, false))
        //失败 ,执行拒绝策略
        reject(command);
}

ctl是什么?它贯穿了整个线程池

//ctl贯穿了整个线程池
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }
    private static final int COUNT_BITS = Integer.SIZE - 3;//29
    //将 1 的二进制向左位移29位,再减 1 表示最大线程容量00011111111111111111111111111111
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
                                                       
    //接受新任务并执行队列中的任务     11100000000000000000000000000000
    private static final int RUNNING    = -1 << COUNT_BITS;
    //不接受新任务,执行队列中的任务    00000000000000000000000000000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    //不接收新任务,不执行队列中的任务,中断正在执行中的任务  00100000000000000000000000000000
    private static final int STOP       =  1 << COUNT_BITS;       //所有的任务都已结束,线程数量为0,处于改状态的线程池即将调用terminated()方法
    // 01000000000000000000000000000000
    private static final int TIDYING    =  2 << COUNT_BITS;
    //terminated()方法执行完成 
    // 01100000000000000000000000000000
    private static final int TERMINATED =  3 << COUNT_BITS;

//RUNNING  -1左移29位
//-1的二级制表示? 负数的二进制 是正数的反码再+1(即补码)
// 1的二进制      00000000000000000000000000000001
// 反码          11111111111111111111111111111110
//-1的二进制      11111111111111111111111111111111
//左移29位        11100000000000000000000000000000
//ctl  二进制的值 | 0 得到的结果仍然是 11100000000000000000000000000000

addworker方法就是增加工作线程

//增加工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {//自旋
        int c = ctl.get();
        int rs = runStateOf(c);
       //如果state状态大于等于SHUTDOWN,并且!(state状态等于SHUTDOWN,firstTask为空,队列不为空)
       //上面是什么意思?线程已经被shutdown,但是如果队列里面还有任务,可以添加新线程来处理任务,反之一        //个条件不满足,则 return false
       // Check if queue empty only if necessary.
        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,core为true代表添加的核心线程,反之
                return false;
            if (compareAndIncrementWorkerCount(c))//cas操作工作线程+1
                break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)  //如果此时ctl发生变化,重新自旋
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }
   /*---------------------------------------------------------------上面为了工作线程+1,下面真正的new Worker()-------------------------------*/
    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)
            //如果失败 workers.remove(w);decrementWorkerCount(),取消上面操作,类似于事务回滚
            addWorkerFailed(w);
    }
    return workerStarted;
}

如果addworker过程中失败了,执行addWorkerfFailed方法

private void addWorkerFailed(Worker w) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
            workers.remove(w);
        decrementWorkerCount();
        tryTerminate();
    } finally {
        mainLock.unlock();
    }
}

Worker本身又是什么?

private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    private static final long serialVersionUID = 6138294804551838833L;
    final Thread thread; //工作线程执行task
    Runnable firstTask;  //任务线程
    volatile long completedTasks; //已经完成的任务数

    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }
    public void run() {
        //工作线程执行
        runWorker(this);
    }
    protected boolean isHeldExclusively() {
        return getState() != 0;
    }

    protected boolean tryAcquire(int unused) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }
    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }
    public void lock()        { acquire(1); }
    public boolean tryLock()  { return tryAcquire(1); }
    public void unlock()      { release(1); }
    public boolean isLocked() { return isHeldExclusively(); }

    void interruptIfStarted() {
        Thread t;
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }
}

runWorker方法

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        //如果工作线程里面的任务不为空,或者队列里面的任务不为空,一直while循环执行任务task.run();
        while (task != null || (task = getTask()) != null) {
            //这里上锁并不是为了并发,为了在 shutdown()时不终止正在运行的 worker
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                //前置处理器,线程池本身没有实现
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } 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);
    }
}

processWorkerExit方法

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        completedTaskCount += w.completedTasks;
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }

    tryTerminate();

    int c = ctl.get();
    if (runStateLessThan(c, STOP)) {
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        addWorker(null, false);
    }
}

getTask方法作用:从队列中获取任务

//从队列中获取任务
private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?

    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);
        //线程池已经被shutdown并且(STOP或者队列为空)
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);
//allowCoreThreadTimeOut如果为true则代表超时时间对核心线程池也有用,即核心线程池也能被回收
        //wc > corePoolSize代表操作最大线程数回收该线程
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
  
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
            Runnable r = timed ?
                //(核心线程或者最大线程)timeout取队列
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
               //阻塞方法(核心线程),阻塞取队列
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;//代表队列中没有待运行的任务了,进入下一次循环的时候 timed && timedOut 为true,并且workQueue.isEmpty()也是true,就会return null,线程被回收
} catch (InterruptedException retry) {             timedOut = false; } } }

 线程池提供的 四大拒绝策略

/**
 * 调用线程执行任务
 */
public static class CallerRunsPolicy implements RejectedExecutionHandler {

    public CallerRunsPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

/**
 * throw异常
 */
public static class AbortPolicy implements RejectedExecutionHandler {
    /**
     * Creates an {@code AbortPolicy}.
     */
    public AbortPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}

/**
 * 直接丢弃,啥也不干
 */
public static class DiscardPolicy implements RejectedExecutionHandler {

    public DiscardPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}

/**
 * 丢弃最老的任务
 */
public static class DiscardOldestPolicy implements RejectedExecutionHandler {

    public DiscardOldestPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}

使用线程池的优点

    1.重用线程池的线程,避免因为线程的创建和销毁锁带来的性能开销

    2.有效控制线程池的最大并发数,避免大量的线程之间因抢占系统资源而阻塞

    3.能够对线程进行简单的管理,并提供一下特定的操作如:可以提供定时、定期、单线程、并发数控制等功能

  
   
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!