【深入浅出java线程池执行过程】

引言

在Java并发编程中,线程池是一种被广泛应用的资源管理工具,它能够有效地管理和控制程序中的线程数量,从而提高系统性能、减少系统资源消耗。本文将深入剖析Java线程池的工作机制与执行过程。

一、线程池的基本概念

Java中的线程池主要由java.util.concurrent ThreadPoolExecutor类实现,其核心组件包括:工作队列(如ArrayBlockingQueue)、线程池(包含核心线程和非核心线程)以及拒绝策略等。线程池的主要任务是接收外部提交的任务并调度线程进行执行。

二、线程池的工作流程

直接上图:

线程池执行过程主要分为四个阶段

任务提交阶段

当我们调用ThreadPoolExecutor.execute(Runnable task)方法向线程池提交一个任务时,线程池内部会经历以下步骤:

  1. 判断当前线程池中的线程数量是否小于核心线程数:如果是,线程池会创建一个新的工作线程来执行这个任务,并将其初始化,然后调用线程的start()方法启动它。
  2. 若当前线程数不小于核心线程数,线程池会尝试将任务添加到工作队列(如ArrayBlockingQueue)。这里的“尝试”意味着如果队列已满,那么就会触发下一种处理方式。
  3. 如果工作队列已满,线程池会检查当前线程数是否小于最大线程数。如果小于最大线程数,线程池会创建一个新的线程来处理这个任务;否则,就需要采取拒绝策略来处理无法接受的新任务。

任务获取与执行阶段

每个工作线程都在一个无限循环中运行,它们会不断从工作队列中获取任务并执行。获取任务的过程通常涉及阻塞等待(如使用BlockingQueue的take()方法)。一旦获取到任务,线程就会执行Runnable.run()方法,完成任务的实际工作。

线程扩展与收缩

  • 线程扩展:当线程池需要创建新线程来处理任务时,会调用ThreadFactory.newThread(Runnable r)方法创建新线程。默认的线程工厂会为每个线程赋予有意义的名字,比如"pool-1-thread-1"。
  • 线程收缩:线程池中的非核心线程在完成任务后不会立即销毁,而是进入保持存活状态。只有当这些线程在指定时间内(keepAliveTime参数指定)没有接收到新的任务,并且线程池中的线程数大于核心线程数时,这些空闲线程才会被终止。

拒绝策略

四种常见的拒绝策略如下:

  • AbortPolicy:默认拒绝策略,直接抛出RejectedExecutionException异常。
  • CallerRunsPolicy:调用者所在线程负责执行任务,这将降低新任务的提交速度。
  • DiscardPolicy:默默地丢弃任务,不执行也不抛出异常。
  • DiscardOldestPolicy:移除工作队列中最旧的任务(最先入队但尚未被执行的任务),然后重新尝试提交当前任务。

线程池核心参数

Java线程池的核心类是java.util.concurrent.ThreadPoolExecutor,它提供了丰富的参数用于定制线程池的行为。以下是ThreadPoolExecutor的主要构造函数参数及其含义:

  1. corePoolSize: 这是线程池的基本大小,即线程池即使在空闲时也会维持的最小线程数量。只要有任务提交过来,就会优先创建至corePoolSize个线程来处理任务。
  2. maximumPoolSize: 这是线程池能容纳的最大线程数。当线程池中的所有线程都处于活动状态且工作队列已满时,线程池会尝试增加更多的线程来处理任务,直到达到这个上限。
  3. keepAliveTime: 当线程池中线程数量超过corePoolSize时,多余的空闲线程在多长时间内(无新任务提交)仍不被使用就会被终止。这个时间长度是以TimeUnit指定的时间单位来衡量的。
  4. TimeUnit: keepAliveTime参数的时间单位,可以是纳秒(NANOSECONDS)、微秒(MICROSECONDS)、毫秒(MILLISECONDS)、秒(SECONDS)、分钟(MINUTES)、小时(HOURS)或天(DAYS)。
  5. BlockingQueue workQueue: 任务队列,用于存储等待执行的任务。可以选择不同的队列类型,例如无界队列(如LinkedBlockingQueue)、有界队列(如ArrayBlockingQueue)或其他满足BlockingQueue接口的自定义队列。
  6. ThreadFactory threadFactory: 用于创建新线程的工厂类,可以通过自定义ThreadFactory来设定新线程的名称、优先级和其他属性。
  7. RejectedExecutionHandler handler: 拒绝策略,当线程池和任务队列都无法处理新的任务时,会调用这个策略的rejectedExecution方法来处理被拒绝的任务。Java提供了一系列内置的拒绝策略如AbortPolicy、CallerRunsPolicy、DiscardPolicy和DiscardOldestPolicy,也可以自定义拒绝策略。

线程池实践

创建一个核心线程池数为2,最大线程数为3,阻塞队列大小为2的线程池。

下面的代码中,执行一次任务需要5000MS,而6个任务是一次性提交进去的,其中第四个任务就会因为 无法被核心线程执行,无法加入等待队列,无法创建新的非核心线程执行,而执行拒绝策略。

public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(2,
                3,
                0, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(2));

        for (int i = 0; i < 6; i++) {
            executorService.execute(() -> {
                try {
                    Date date = new Date();
                    System.out.println("线程:" + Thread.currentThread().getName() + "报时:" + date);
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }

            });

            System.out.println("等待队列中现在有" + executorService.getQueue().size() + "个任务");
            Thread.sleep(500);
        }
    }

运行结果如下:

image-20240216180433376

从运行结果中,可以看出

1、前面两个任务是通过核心线程池来执行

image-20240216181146228

2、第3、4个任务会被放到等待队列中

image-20240216181404081

3、等待队列满了后,第五个任务是通过创建了一个非核心线程来执行任务,这是第三个线程

image-20240216181432321

4、第六个任务由于核心线程池,等待队列,最大线程池数都已经达到最大,所以执行拒绝策略

image-20240216181651763

5、从队列中获取任务,由于核心线程里面的任务已经执行完成,所以通过核心线程执行

image-20240216181955378

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我无法回答关于"深入浅出Java虚拟机PDF"的问题。但是,我可以告诉你关于Java虚拟机的一些信息。Java虚拟机(JVM)是Java程序的运行环境,它负责将Java字节码转换为机器语言执行程序。通过使用不同的虚拟机参数,可以对JVM进行配置和调优。 通过设置-Xss参数,可以指定每个线程的Java虚拟机栈内存大小。在JDK 1.4中,默认为256K,在JDK 1.5及更高版本中,默认为1M。例如,使用java -Xss2M命令可以将线程栈内存大小设置为2M。 Java虚拟机使用ClassLoader加载类。所有其他类的加载器都是Java实现的,并继承自抽象类java.lang.ClassLoader。 当老年代空间不足时,可能会触发Full GC。但是,并不建议使用这种方式来管理内存,而是让虚拟机自行管理。因为手动执行Full GC可能会导致性能问题。 希望以上信息对你有所帮助。如果你对Java虚拟机还有其他问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [深入浅出JAVA虚拟机](https://blog.csdn.net/loulanyue_/article/details/101075303)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值