Java 线程 — ThreadPoolExecutor

线程池

线程池处理流程

  • 核心线程池:创建新线程执行任务,需要获取全局锁
  • 队列:将新来的任务加入队列
  • 线程池:大于corePoolSize,并且队列已满,小于maxPoolSize,创建新的worker执行任务
  • 线程池已满(达到max)处理策略:大于线程最大处理能力,大于maxPoolSize,选择拒绝策略

尽可能避免获取全局锁,corePoolSize就是这个作用,线程池开始处理任务,预热达到corePoolSize之后,将新来的任务放入队列

execute

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    // ctl是一个AtomInteger,低29为表示线程数workerCount,高3位表示线程池运行状态runState
    int c = ctl.get();
    // 当前前程数小于核心线程数corePoolSize,新建核心线程处理任务
    if (workerCountOf(c) < corePoolSize) {
    	// 第二个参数为true表示新建的核心线程
        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);
    }
    // 如果放入队列失败(队列已满),则新建线程处理任务,第二个参数为false表示新建的是非核心线程
    else if (!addWorker(command, false))
    	// 如果已经超过最大线程数,采取相应的拒绝策略
        reject(command);
}

// 第一个参数是需要运行的任务
// 第二个参数是为了区分核心线程和非核心线程,用来确定线程池的边界是corePoolSize还是maxPoolSize
// 本方法的作用就是新建一个worker线程并启动
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

		// 循环确保CAS操作成功
        for (;;) {
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            // 成功增加workerCount则跳出外层循环,开始新建线程
            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 {
        final ReentrantLock mainLock = this.mainLock;
        // 新建worker线程
        w = new Worker(firstTask);
        final Thread t = w.thread;
        if (t != null) {
        	// 可重入锁,加锁
            mainLock.lock();
            try {
                // Recheck while holding lock.
                // Back out on ThreadFactory failure or if
                // shut down before lock acquired.
                int c = ctl.get();
                int rs = runStateOf(c);

                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    // 将新建的线程放入线程池中,其实就是一个HashSet
                    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;
}

创建线程

// 在addWorker中新建线程
w = new Worker(firstTask);

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

// 这里以ThreadFactory的一个实现DefaultThreadFactory为例
DefaultThreadFactory() {
    SecurityManager s = System.getSecurityManager();
    // 新建一个线程组,线程池中所有线程都由线程组统一管理
    group = (s != null) ? s.getThreadGroup() :
                          Thread.currentThread().getThreadGroup();
    namePrefix = "pool-" +
                  poolNumber.getAndIncrement() +
                 "-thread-";
}

// 新建线程
public Thread newThread(Runnable r) {
	// 新建的线程属于线程组group,r为Worker对象
    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;
}

线程池中的worker线程执行任务

// 在addWorker中会启动worker线程
if (workerAdded) {
    t.start();
    workerStarted = true;
}

// 线程启动之后会执行worker的run方法
// 调用外部类ThreadPoolExecutor的runWorker方法
public void run() {
    runWorker(this);
}

// runWorker,worker线程循环执行来自workerQueue的任务(除firstTask外)
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    // 新建线程以后会执行第一个任务,新建Worker线程的时候传入的任务
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
    	// worker不断从workerQueue中getTask执行,
        // 如果没有获取任务并且返回,则while循环结束,worker线程结束
        while (task != null || (task = getTask()) != null) {
            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 {
                	// 调用run方法执行
                    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);
    }
}

// 从workerQueue中获取task,workerQueue是BlockingQueue
// 如果返回null,则会导致worker线程结束
private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?

    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

		// 决定没有任务的时候线程是结束还是等待任务
        boolean timed;      // Are workers subject to culling?

        for (;;) {
            int wc = workerCountOf(c);
            // 当allowCoreThreadTimeOut为true或者当前线程数大于核心线程数的时候timed为true
            // allowCoreThreadTimeOut为true:允许线程没有任务的时候超时退出
            // wc > corePoolSize:表示当前线程数足够,可以结束,以维持核心线程数
            timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if (wc <= maximumPoolSize && ! (timedOut && timed))
                break;
            if (compareAndDecrementWorkerCount(c))
                return null;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }

        try {
        	// workQueue.poll:等待keepAliveTime纳秒之后,如果获取到则返回任务,否则返回null
            // workQueue.take:如果没有获取到任务,线程会一直阻塞,直到被唤醒(什么时候会被唤醒:新加入task的时候,poll后队列中元素数依然大于1个,队列中元素数等于capacity),所以take如果返回的话一定是非空的
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

线程池满之后的拒绝策略

CallerRunsPolicy

直接在调用线程池所在的线程运行(调用)

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
    	// 直接调用run方法
        r.run();
    }
}

AbortPolicy

throw Exception

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

DiscardPolicy

直接丢弃,不做任何操作

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

DiscardOldestPolicy

丢弃最老任务的策略

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
    	// 移除第一个任务,也就是最老(最先进来的)任务
        e.getQueue().poll();
        // 执行当前传入的任务
        e.execute(r);
    }
}

问题

线程池的“池”体现在哪里

  • 平时使用线程都是直接继承Thread然后,调用start,然后Thread.start通过native调用创建新的线程并回调自己定义的run方法,所以每次调用一次run方法都需要新建一个线程
  • 线程池就是,启动一个线程(Worker)调用完一个run(直接调用,不再通过Thread.start)方法之后并不会立即退出,会运行在队列中等待的其他run方法(这里是循环,从队列中获取),如果队列中没有需要继续运行的线程则当前worker线程会休眠
posted @ 2016-11-19 11:28  lacker  阅读(542)  评论(0编辑  收藏  举报