Java线程池详细解读

Java线程池详细解读

什么是线程池?

线程池是一种用于多线程管理的机制,它可以有效管理将要执行的任务,减轻了创建和销毁线程的负担。通过复用现有线程,避免了大量线程创建和销毁过程中的开销,从而提高了应用程序的性能和可伸缩性。

线程池的优势

线程池的优势主要体现在以下几个方面:

  • 更好的利用 CPU 资源和减少上下文切换的时间开销。
  • 可以根据需要创建和回收线程,从而避免了线程创建和销毁的开销。
  • 能够控制线程的数量和执行优先级,防止过多的请求导致程序崩溃。
  • 能够通过设置队列等待机制,使得任务顺序执行进而避免线程竞争。

线程池的实现方式

在 Java 中,可以使用 java.util.concurrent 包中的线程池来实现线程管理。常用的线程池类型有以下四种:

  1. FixedThreadPool:该线程池类型的核心线程数是固定的,同时也允许在池中创建的线程数量保持不变。一般情况下它使用无界队列,即可以放入无限多的任务。
  2. CachedThreadPool:该线程池类型的核心线程数是 0,为非固定值。当池中线程数量不够用时,会创建新的线程,而池中线程数量缩减时,会回收后面的线程。此种类型线程池在取得一个工作线程时总是先尝试复用之前的线程。
  3. SingleThreadExecutor:该线程池类型只有一个线程,每提交一个任务就会产生一个任务。
  4. ScheduledThreadPool:该线程池支持延迟执行和定时执行的任务。

线程池的实现过程

使用线程池的主要过程是:

  1. 创建一个线程池对象。
  2. 创建任务并提交到线程池中执行。
  3. 等待任务执行完成,关闭线程池。

它的基本代码如下所示:

// 创建一个大小固定为 5 的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);

// 创建任务并提交到线程池中执行
executorService.execute(new Runnable() {
    @Override
    public void run() {
        // 业务处理逻辑
    }
});

// 等待任务执行完成,关闭线程池
executorService.shutdown();

示例一:使用 FixedThreadPool

下面是一个使用 FixedThreadPool 的示例代码:

// 创建一个核心线程数为 5 的固定线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

// 提交至少 10 个任务到线程池中
for (int i = 1; i <= 10; i++) {
    fixedThreadPool.execute(new Task(i));
}

// 关闭线程池
fixedThreadPool.shutdown();

class Task implements Runnable {
    private int taskId;

    public Task(int taskId) {
        this.taskId = taskId;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId);
    }
}

在该示例中,线程池的核心线程数是 5,然后将 10 个任务添加到线程池中进行执行。程序的执行结果为:

pool-1-thread-2 执行任务 2
pool-1-thread-1 执行任务 1
pool-1-thread-3 执行任务 3
pool-1-thread-4 执行任务 4
pool-1-thread-5 执行任务 5
pool-1-thread-5 执行任务 6
pool-1-thread-2 执行任务 7
pool-1-thread-4 执行任务 8
pool-1-thread-1 执行任务 9
pool-1-thread-3 执行任务 10

示例二:使用 ScheduledThreadPool

下面是一个使用 ScheduledThreadPool 的示例代码:

// 创建一个大小固定为 5 的线程池
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

// 延迟 1 秒后执行任务
scheduledExecutorService.schedule(new Task(), 1L, TimeUnit.SECONDS);

// 延迟 3 秒后执行任务
scheduledExecutorService.schedule(new Task(), 3L, TimeUnit.SECONDS);

// 每 1 秒执行一次任务
scheduledExecutorService.scheduleAtFixedRate(new Task(), 0L, 1L, TimeUnit.SECONDS);

// 每 3 秒执行一次任务
scheduledExecutorService.scheduleWithFixedDelay(new Task(), 0L, 3L, TimeUnit.SECONDS);

// 关闭线程池
scheduledExecutorService.shutdown();

class Task implements Runnable {
    @Override
    public void run() {
        System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
}

在该示例中,线程池的核心线程数是 5,然后分别在 1s 和 3s 后执行任务,每隔 1s 和 3s 执行一次任务。程序的执行结果为:

当前时间:2021-11-06 16:06:16
当前时间:2021-11-06 16:06:17
当前时间:2021-11-06 16:06:17
当前时间:2021-11-06 16:06:18
当前时间:2021-11-06 16:06:18
当前时间:2021-11-06 16:06:19
当前时间:2021-11-06 16:06:19
当前时间:2021-11-06 16:06:20
当前时间:2021-11-06 16:06:20
当前时间:2021-11-06 16:06:21

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java线程池详细解读 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 一篇文章带你了解Java 中序列化与反序列化

    一篇文章带你了解Java 中序列化与反序列化 引言 在Java编程中,可能需要将对象存储在文件中或通过网络传输。使用序列化来处理这些任务是很常见的方法。本篇文章将介绍Java中的序列化和反序列化的概念和用法,给你提供一个完整的攻略。 Serializable 接口 Java 中的序列化和反序列化要求被序列化的类必须实现 Serializable 接口。实现 …

    Java 2023年5月26日
    00
  • Java创建多线程服务器流程

    创建多线程服务器是Java网络编程的重要部分,具有很高的实用价值。以下是实现Java创建多线程服务器的完整攻略。 过程 第一步:创建ServerSocket对象 ServerSocket类是Java语言提供的Socket接口,用于管理服务器端的网络地址和端口号等信息。创建ServerSocket对象的代码如下: ServerSocket server = n…

    Java 2023年5月26日
    00
  • 详细聊聊Spring MVC重定向与转发

    详细聊聊Spring MVC重定向与转发 在Spring MVC中,重定向和转发是两种常见的请求转发方式。本文将详细介绍Spring MVC中重定向和转发的概念、区别、使用方法以及示例。 重定向 重定向是指将请求重定向到另一个URL。在Spring MVC中,我们可以使用RedirectView或RedirectAttributes类来实现重定向。下面是实现…

    Java 2023年5月17日
    00
  • SpringBoot 监控管理模块actuator没有权限的问题解决方法

    我来为您详细讲解“SpringBoot 监控管理模块actuator没有权限的问题解决方法”的完整攻略。 问题描述 在使用 SpringBoot 监控管理模块 actuator 时,可能会遇到没有权限的问题,例如访问 http://localhost:8080/actuator 时出现 {“timestamp”:”2021-07-28T12:34:56.78…

    Java 2023年5月20日
    00
  • Java线程死锁代码详解

    这里我给你提供一份“Java线程死锁代码详解”的攻略,希望能对你有所帮助。 背景介绍 线程死锁在多线程环境下是非常常见的情况,而解决线程死锁也非常困难,因此需要我们对线程死锁有一个深入的了解。本文将详细讲解Java线程死锁的原因、示例以及如何解决死锁。 什么是线程死锁? 当两个或更多的线程互相持有对方所需要的资源,同时等待对方释放资源,就会出现线程死锁。可以…

    Java 2023年5月24日
    00
  • springboot自定义starter方法及注解实例

    Spring Boot自定义Starter方法及注解实例 Spring Boot是一个快速开发框架,可以帮助开发人员快速构建Web应用程序。在Spring Boot中,我们可以使用自定义Starter来封装一些常用的依赖和配置,以便在多个项目中重复使用。本文将介绍Spring Boot自定义Starter的方法及注解实例,并提供两个示例。 自定义Starte…

    Java 2023年5月15日
    00
  • 一文彻底搞懂Java和JDK的版本命名问题

    一文彻底搞懂Java和JDK的版本命名问题 Java和JDK的版本命名规则 Java和JDK的版本命名包含三部分:主版本号、次版本号和更新版本号,如:1.8.0、11.0.1等,其中: 主版本号:代表Java/JDK发行的主要版本号,用于标识整个Java/JDK版本的变化,从1开始递增。例如Java 8和Java 11的主版本号分别为1和11。 次版本号:代…

    Java 2023年5月26日
    00
  • Mybatis中设置全局变量的方法示例

    设置Mybatis的全局变量,需要在Mybatis的配置文件中进行配置。以下是设置Mybatis全局变量的步骤: 1. 在Mybatis的配置文件中添加标签,定义全局变量 <configuration> <properties> <property name="myVar1" value="100&…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部