线程池原理(JDK1.8)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38278878/article/details/81456510

Java中的线程池

ThreadPoolExecutor是线程池类。对于线程池,可以通俗的将它理解为”存放一定数量线程的一个线程集合。线程池允许若个线程同时允许,允许同时运行的线程数量就是线程池的容量;当添加的到线程池中的线程超过它的容量时,会有一部分线程阻塞等待。线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理。

组成(这部分转自线程池原理——skywang12345

// 阻塞队列
private final BlockingQueue<Runnable> workQueue;

// 互斥锁
private final ReentrantLock mainLock = new ReentrantLock();

// 线程集合。一个Worker对应一个线程。
private final HashSet<Worker> workers = new HashSet<Worker>();

// “终止条件”,与“mainLock”绑定。
private final Condition termination = mainLock.newCondition();

// 线程池中线程数量曾经达到过的最大值。
private int largestPoolSize;

// 已完成任务数量
private long completedTaskCount;

// ThreadFactory对象,用于创建线程。
private volatile ThreadFactory threadFactory;

// 拒绝策略的处理句柄。
private volatile RejectedExecutionHandler handler;

// 保持线程存活时间。
private volatile long keepAliveTime;

private volatile boolean allowCoreThreadTimeOut;

// 核心池大小
private volatile int corePoolSize;

// 最大池大小
private volatile int maximumPoolSize;

1.workers

workers是HashSet类型,即它是一个Worker集合。而一个Worker对应一个线程,也就是说线程池通过workers包含了”一个线程集合”。当Worker对应的线程池启动时,它会执行线程池中的任务;当执行完一个任务后,它会从线程池的阻塞队列中取出一个阻塞的任务来继续运行。
wokers的作用是,线程池通过它实现了”允许多个线程同时运行”。

2.workQueue

workQueue是BlockingQueue类型,即它是一个阻塞队列。当线程池中的线程数超过它的容量的时候,线程会进入阻塞队列进行阻塞等待。
通过workQueue,线程池实现了阻塞功能。

3. mainLock

mainLock是互斥锁,通过mainLock实现了对线程池的互斥访问。

4. corePoolSize和maximumPoolSize

corePoolSize是”核心池大小”,maximumPoolSize是”最大池大小”。它们的作用是调整”线程池中实际运行的线程的数量”。
例如,当新任务提交给线程池时(通过execute方法)。
– 如果此时,线程池中运行的线程数量< corePoolSize,则创建新线程来处理请求。
– 如果此时,线程池中运行的线程数量> corePoolSize,但是却< maximumPoolSize;则仅当阻塞队列满时才创建新线程。
如果设置的 corePoolSize 和 maximumPoolSize 相同,则创建了固定大小的线程池。如果将 maximumPoolSize 设置为基本的无界值(如 Integer.MAX_VALUE),则允许池适应任意数量的并发任务。在大多数情况下,核心池大小和最大池大小的值是在创建线程池设置的;但是,也可以使用 setCorePoolSize(int) 和 setMaximumPoolSize(int) 进行动态更改。

5. poolSize

poolSize是当前线程池的实际大小,即线程池中任务的数量。

6. allowCoreThreadTimeOut和keepAliveTime

allowCoreThreadTimeOut表示是否允许”线程在空闲状态时,仍然能够存活”;而keepAliveTime是当线程池处于空闲状态的时候,超过keepAliveTime时间之后,空闲的线程会被终止。

7. threadFactory

threadFactory是ThreadFactory对象。它是一个线程工厂类,”线程池通过ThreadFactory创建线程”。

8. handler

handler是RejectedExecutionHandler类型。它是”线程池拒绝策略”的句柄,也就是说”当某任务添加到线程池中,而线程池拒绝该任务时,线程池会通过handler进行相应的处理”。



原理(源码是JDK1.8)

 public void execute(Runnable command) {
     if (command == null)
         throw new NullPointerException();

     int c = ctl.get();
     /*
         1、判断当前的工作线程是否小于线程池里的核心线程,如果满足,则创建一个新的工作线程来执行任务。
         如果不满足,则进入下个流程。

         注意:此时addWorker的第二个参数为true;
     */ 
     if (workerCountOf(c) < corePoolSize) {
         if (addWorker(command, true))
             return;
         c = ctl.get();
     }
     /*
        2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。
        如果工作队列满了,则进入下个流程。
    */
     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);
     }
     //3、尝试创建线程    注意:此时addWorker的第二个参数为false,下面会解释
     else if (!addWorker(command, false))
         reject(command);
 }

//该方法用于创建线程,注意该方法的第二个参数core
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);
                /*
                    当core为false时,下面判断线程池corePoolSize和maximumPoolSize 的差值,如果此时,
                    线程池中运行的线程数量> corePoolSize,但是却< maximumPoolSize,则会继续创建一个
                    新的工作线程。
                */
                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;
    }

总结

1、判断当前的工作线程是否小于线程池里的核心线程,如果满足,则创建一个新的工作线程来执行任务。不满足则进入下个流程。

2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。

3、判断线程池corePoolSize和maximumPoolSize 的差值,如果此时,线程池中运行的线程数量> corePoolSize,但是却< maximumPoolSize,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

猜你喜欢

转载自blog.csdn.net/weixin_38278878/article/details/81456510
今日推荐