java.util.concurrent learning (seven) ThreadPoolExecutor

ThreadPoolExecutor inherited AbstractExecutorService , it is the main way to achieve a thread pool thread pool created Executors factory. You can quickly create a thread pool thread pool by the factory, but this approach also has some disadvantages. For example: Executors.newFixedThreadPool (int nThreads) to create a thread pool thread core fixed number, not the flexibility to expand maximum number of threads; newCachedThreadPool way the maximum number of threads designed to Integer.MAX_VALUE, in this way likely to cause insufficient memory, is not recommended. If you want to achieve business by way of the thread pool, it is best to thread pool systematic understanding of project design truly meet the thread pool is the best solution. Here we come together to learn about it.

1. ThreadPoolExecutor recognized by the most basic method of construction

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

There are four ThreadPoolExecutor constructor, the other three parameters are controlled to achieve this by calling the constructor. Look at the source code:

/**
  *corePoolSize    核心线程数,除非设置了allowCoreThreadTimeOut,否则核心线程将会一直在
  *                保存在池中,即使是闲置的。核心线程可以帮助我们快速执行任务,避免了创建
  *                线程带来的消耗。(corePoolSize>=0)
  *
  *maximumPoolSize 最大线程数,线程池中允许存在的最大线程数,可以用来控制内存使用,避免不
  *                必要的线程创建。(maximumPoolSize>0&&maximumPoolSize>=corePoolSize)
  *
  *keepAliveTime   非核心线程闲置超时时间。当线程池的线程数超过核心线程数时,非核心线程将
  *                等待新任务的时间不能超过keepAliveTime,一旦超过将自动terminating。      
  *                (keepAliveTime>0)
  *
  *unit            keepAliveTime的时间单位。
  *
  *workQueue       等待执行的线程队列,该队列中只保存被submitted的线程。(not null)
  *
  *threadFactory   生产线程的工厂。(not null)
  *
  *handler         线程拒绝策列。当线程池和队列已满时,通过该handler来处理新提交的任务。
  *                (not null)
  **/
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> 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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

2. The property is set allowCoreThreadTimeOut

  /**
    *该参数需要配合keepAliveTime来使用,当设置为true时,核心线程会像非核心线程一样遵循
    *keepAliveTime的超时规则。默认false。
    **/
public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
               //当设置为true时,立即打断限制的核心线程
                interruptIdleWorkers();
        }
    }

   private void interruptIdleWorkers() {
        interruptIdleWorkers(false);
    }

//onlyOne  是否只打断一个线程
private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

3. Submit Thread execute

  /**
    *@param command 要提交的任务(not null)
    *
    *@desc  提交一个任务,线程池会在将来的某一时刻执行该任务,如果线程池已满,则会通过拒绝策略来 
    *       处理该任务
    **/
public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * 总共有三步:
         *
         *
         * 1. 检查当前线程数是否少于核心线程数。如果当前线程数少于核心线程数,
         *那么创建一个新的线程来执行该任务。通过调用addWorker进行原子操作检查
         *线程状态和数目,从而避免出现错误的溢出警戒值。
         *
         * 2. 如果一个任务可以成功的添加到队列,那么仍然需要二次检查是否需要添
         *加一个线程或者线程池是否已经关闭。
         *
         * 3. 如果无法增加任务到队列,那就尝试添加一个线程。如果失败了,那么需要
         *通过拒绝策略来处理。
         */
        int c = ctl.get();
        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.
            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;
    }

 

Guess you like

Origin blog.csdn.net/top_explore/article/details/90740214