线程池ThreadPoolExecutor的原理

本文介绍了Java中创建线程的两种方法,重点讲解了通过Executors框架创建线程池的过程及ThreadPoolExecutor的重要参数。包括线程池的基本大小、最大数量、保持时间、阻塞队列、拒绝策略和线程工厂等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.创建线程的方式

Java中创建线程有两种方式:
1. 通过Thread创建线程
2. 通过Executors框架创建线程

2.Executors框架的使用

其中通过Executors框架可以创建线程池,相比每个任务创建一个线程具有更好的性能和响应。
Executors提供了四个创建线程池的方法:

  1. newFixedThreadPool 创建一个固定长度的线程池
  2. newFixedThreadPool 创建一个可缓存的线程池
  3. newSingleThreadExecutor 创建一个单线程
  4. newScheduledThreadPool 创建一个固定长度的线程池,而且以延迟或定时的方式执行任务,类似于Timer

3.ThreadPoolExecutor的重要参数

这四个方法最终是通过创建ThreadPoolExecutor来完成线程池的创建,首先说说ThreadPoolExecutor的几个参数:
1)corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。

2)maximumPoolSize(线程池最大数量):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是,如果使用了无界的任务队列这个参数就没什么效果。

3)keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。所以,如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程的利用率。

4)TimeUnit:时间单位,相比只用ms为单位更加的直观.

5)BlockingQueue:阻塞队列,队列空和队列满时调用它的take方法会阻塞.

6)RejectedExecutionHandler:当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。在JDK 1.5中Java线程池框架提供了以下4种策略:

  • AbortPolicy:直接抛出异常。

  • CallerRunsPolicy:只用调用者所在线程来运行任务。

  • DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。

  • DiscardPolicy:不处理,丢弃掉。

7)ThreadFactory:创建线程的工厂模式,可以指定线程的名字,是否后台线程等属性。

4.ThreadPoolExecutor的原理

ThreadPoolExecutor中最重要的方法,即execute方法,就是ThreadPoolExecutor创建线程池的原理,它分为4个步骤:

1)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
2)如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
3)如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。
4)如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。
源码如下:

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();
        }
        if (isRunning(c) && workQueue.offer(command)) {//添加任务到阻塞队列BlockingQueue中,如果BlockingQueue没有元素,会一直阻塞,直到元素添加进来。
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);//调用RejectedExecutionHandler
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);//没有可用线程,检查最大线程大小
        }
        else if (!addWorker(command, false))
            reject(command);
    }
  private boolean addWorker(Runnable firstTask, boolean core) {
        ...
        ...
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            w = new Worker(firstTask);//Worker实现了Runnable, 在它的run方法中执行了任务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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值