Java线程池的几种实现方法和区别介绍实例详解

Java线程池的几种实现方法和区别介绍

什么是线程池

在线程池中,线程的创建和销毁都由线程池管理器来处理,线程池中包括一组线程,线程池会根据配置的参数来动态调整线程池中线程的数量。线程池中的线程可以被多个任务共享,使线程的创建和销毁开销及竞争锁等问题得以优化。

为什么要使用线程池

线程池的主要目的是为了控制并发执行的线程数,有以下几个优点:

  • 降低线程的创建和销毁的开销。
  • 重复利用已经创建的线程,避免创建新的线程所带来的开销。
  • 避免大量线程抢占系统资源导致系统负载过大而崩溃的风险。
  • 更好地管理线程,提供更加灵活,强大的线程管理能力。

线程池的实现方法

在Java中,线程池是由java.util.concurrent包提供的,其中提供了多种类型的线程池,常用的有以下几种:

  • newFixedThreadPool
  • newCachedThreadPool
  • newScheduledThreadPool
  • newSingleThreadExecutor
  • ThreadPoolExecutor

newFixedThreadPool

newFixedThreadPool(int nThreads)方法创建一个有固定大小的线程池,每次提交一个任务就创建一个线程,直到线程数量达到线程池的最大容量。线程池的大小一旦达到最大值,就会保持不变,如果有多余的任务需要执行,就必须等待线程池有空闲的线程才能执行。

示例代码:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {
    fixedThreadPool.execute(new Task(i));
}

该示例代码会创建一个大小为5的线程池,接着往线程池中提交了10个任务。由于线程池的大小为5,因此最多同时执行5个任务,剩下的任务会等待有空闲的线程再去执行。

newCachedThreadPool

newCachedThreadPool()方法创建一个可缓存的线程池,如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲的线程,当任务数增加时,会自动添加新的线程来处理任务。

示例代码:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

for (int i = 0; i < 10; i++) {
    cachedThreadPool.execute(new Task(i));
}

该示例代码会创建一个可缓存的线程池,接着往线程池中提交了10个任务。由于线程池的大小没有限制,因此可以同时执行10个任务。

newScheduledThreadPool

newScheduledThreadPool(int corePoolSize)方法创建一个固定大小的线程池,可以定时或延时执行任务。该方法返回一个ScheduledExecutorService对象,该对象可以在指定延时后执行任务或按固定延时周期执行任务。

示例代码:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

scheduledThreadPool.schedule(new Task(1), 2, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(new Task(2), 2, 1, TimeUnit.SECONDS);

该示例代码会创建一个大小为5的定时线程池,接着往线程池中提交了两个任务,其中第一个任务会在2秒后执行一次,第二个任务则会在2秒后开始执行,每隔1秒执行一次。

newSingleThreadExecutor

newSingleThreadExecutor()方法创建一个单线程的线程池,所有任务都在同一个线程中执行,保证了所有任务的顺序执行,也避免了线程间的竞争问题。

示例代码:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

for (int i = 0; i < 10; i++) {
    singleThreadExecutor.execute(new Task(i));
}

该示例代码会创建一个单线程的线程池,接着往线程池中提交了10个任务。由于是单线程的线程池,因此所有任务都会按照提交的顺序依次执行。

ThreadPoolExecutor

ThreadPoolExecutor是通过Executors工厂类提供的方法之外,直接创建线程池的实现类,这个类的构造方法比较复杂,需要传入7个参数,分别是:

public ThreadPoolExecutor(int corePoolSize, // 核心线程数
                              int maximumPoolSize, // 最大线程数
                              long keepAliveTime, // 线程最大空闲时间
                              TimeUnit unit, // 时间单位
                              BlockingQueue<Runnable> workQueue, // 等待队列
                              ThreadFactory threadFactory, // 线程工厂
                              RejectedExecutionHandler handler // 拒绝策略
                             )

示例代码:

BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10);
ExecutorService threadPoolExecutor = new ThreadPoolExecutor(
        2, // 核心线程数
        4, // 最大线程数
        1, // 线程最大空闲时间
        TimeUnit.MINUTES, // 时间单位
        queue, // 等待队列
        Executors.defaultThreadFactory(), // 线程工厂
        new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略

for (int i = 0; i < 10; i++) {
    threadPoolExecutor.execute(new Task(i));
}

该示例代码会手动创建一个线程池,该线程池的核心线程数为2,最大线程数为4,空闲线程最长等待时间为1分钟,等待队列容量为10,拒绝策略为丢弃任务并抛出异常。接着往线程池中提交了10个任务,在这个示例中,因为线程池容量不够,多余的任务会被等待队列中的消息存储,直到有空闲线程时,线程池才会将消息从等待队列中取走,进行任务处理。

总结

以上就是Java线程池的几种实现方法及其区别介绍。根据不同需求,选择合适的线程池会更好地提升系统性能、压力测试和控制流量。

参考文献

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java线程池的几种实现方法和区别介绍实例详解 - Python技术站

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

相关文章

  • Java 编程中十个处理异常的建议

    Java 编程中十个处理异常的建议 对于 Java 程序员来说,异常处理是一项必不可少的技能。如何合理地处理异常,提高代码的健壮性和可维护性,是每个程序员都应该重视的问题。这里提供十个处理异常的建议,帮助大家更好地应对各种异常情况。 1. 避免捕获过于宽泛的异常 Java 中存在许多种异常类型,如 NullPointerException、ArrayInde…

    Java 2023年5月27日
    00
  • SpringMVC下实现Excel文件上传下载

    SpringMVC下实现Excel文件上传下载的完整攻略 上传Excel文件 1. 在jsp页面中添加上传表单 表单中的文件上传必须要带上enctype=”multipart/form-data”属性。 <form method="POST" action="/upload" enctype="mult…

    Java 2023年6月15日
    00
  • Nginx启用压缩及开启gzip 压缩的方法

    启用gzip压缩是一种优化网络传输的有效方法,可以减少数据传输的大小,提高性能。Nginx作为一种快速而灵活的Web服务器,支持压缩和gzip模块,并且可以通过简单的配置启用。 以下是Nginx启用gzip压缩的步骤: 1. 检查Nginx是否支持gzip模块 在nginx的安装目录下运行命令 nginx -V 可以列出所有编译参数,以及当前nginx所支持…

    Java 2023年6月15日
    00
  • Gateway+Swagger2配置聚合文档方式

    下面是“Gateway+Swagger2配置聚合文档方式”的完整攻略,包含以下几个步骤: 1. 引入Swagger2依赖 在网关服务的pom.xml文件中添加Swagger2依赖: <dependency> <groupId>io.springfox</groupId> <artifactId>springfo…

    Java 2023年6月3日
    00
  • Spring Boot超详细分析启动流程

    Spring Boot是基于Spring框架的一种快速开发框架,它通过自动化配置和约定大于配置的方式,可以快速的搭建一个Web应用。 Spring Boot启动流程主要分为三个阶段:准备阶段、上下文创建阶段、启动阶段。 准备阶段 Spring Boot准备阶段主要是读取应用程序的配置文件,获取配置文件中自定义的配置内容,并为后续的启动做好一些准备工作。准备阶…

    Java 2023年5月19日
    00
  • Java的Struts框架报错“DuplicateDefinitionException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“DuplicateDefinitionException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中有重复的定义,则可能会出现此。在这种情况下,需要检查配置文件以解决此问题。 类加载问题:如果类加载器无法加载所需的类,则可能会出现此。在这种情况下,需要检查类路径以解决此问题。 以下是两个实例…

    Java 2023年5月5日
    00
  • Spring中使用atomikos+druid实现经典分布式事务的方法

    Spring是一个非常流行的Java框架,可以用于构建各种类型的应用程序,包括分布式应用程序。在分布式应用程序中,经典的分布式事务是非常重要的,它可以确保整个事务的一致性和完整性。Atomikos和Druid是常用的分布式事务解决方案,它们都有很多优点,例如可靠性、高性能和灵活性等。下面是如何在Spring中使用Atomikos和Druid实现经典分布式事务…

    Java 2023年5月20日
    00
  • Win7系统下tomcat7.0配置教程

    下面是Win7系统下tomcat7.0的配置教程的完整攻略: 安装jdk 首先需要安装并配置好Java Development Kit(JDK),可以从Oracle的官网上下载安装包。安装完成后需要配置系统环境变量,具体参考以下步骤: 在“计算机”上右键点击“属性”; 点击“高级系统设置”; 点击“环境变量”; 在“系统变量”中新增“JAVA_HOME”变量…

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