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中的静态内部类是一种内部类,它具有访问外部类的静态成员变量和方法的能力。它与外部类的静态成员是相似的,可以通过类名直接访问。 定义静态内部类 静态内部类的定义方式与成员内部类的定义方式类似,只是需要在内部类名称前面加上static关键字。以下是一个示例: public class OuterClass { private static String …

    Java 2023年4月27日
    00
  • SpringMVC五种类型参数传递及json传递参数

    Spring MVC是一种常用的Web框架,它提供了多种参数传递方式,包括基本类型、对象、集合、数组和JSON等。本文将详细讲解Spring MVC五种类型参数传递及JSON传递参数,并提供两个示例说明。 五种类型参数传递 1. 基本类型参数传递 基本类型参数传递是指将基本类型的值作为请求参数传递给Controller方法。在Spring MVC中,我们可以…

    Java 2023年5月18日
    00
  • 通过Java测试几种压缩算法的性能(附测试代码下载)

    这篇攻略主要介绍了如何使用Java编写测试代码,测试多种常见的压缩算法的性能,以及如何通过性能测试结果对比来选择最佳的压缩算法。以下是详细的步骤: 准备工作 首先,需要下载并安装JMH(Java Microbenchmark Harness)工具。JMH是一个专门用于Java微基准测试的工具集,可以在不同的测试场景下自动化构造和运行测试并得出性能结果。官方网…

    Java 2023年5月23日
    00
  • 如何开发基于Netty的HTTP/HTTPS应用程序

    下面是开发基于Netty的HTTP/HTTPS应用程序的完整攻略: 1. 环境准备 JDK 1.8及以上版本 Maven 3.0及以上版本 Netty 4.1.32.Final及以上版本 2. 创建maven项目 使用Maven创建一个新的项目,添加Netty以及其他必要的依赖: <dependencies> <dependency>…

    Java 2023年6月1日
    00
  • JavaWeb实现文件上传下载功能实例解析

    JavaWeb实现文件上传下载功能实例解析 一、文件上传 文件上传是指将本地机器上的文件通过网络传输到远程服务器上的过程。在JavaWeb中,可以使用Servlet实现文件上传功能。 在上传文件之前,需要先创建一个表单,让用户选择需要上传的文件。具体操作如下: 在HTML中创建一个表单,指定表单的enctype属性值为”multipart/form-data…

    Java 2023年5月20日
    00
  • Java中Arraylist的最大长度

    Java中ArrayList的最大长度 简介 ArrayList是Java中非常常用的数据结构,它是可变长度的数组。ArrayList最大长度由内存大小决定。当数组长度大于内存大小时,便会抛出OutOfMemoryError异常。 ArrayList的初始化长度 初始化ArrayList时可以指定其大小,如下所示: ArrayList<String&g…

    Java 2023年5月26日
    00
  • 详解JDBC对Mysql utf8mb4字符集的处理

    下面是详解JDBC对Mysql utf8mb4字符集的处理的完整攻略: 一、 utf8mb4字符集简介 utf8mb4是MySQL支持的字符集之一,它是UTF-8字符集的超集,支持Emoji表情等特殊字符,如果使用注意不当,可能会导致字符集转换出现问题。 二、 JDBC驱动对utf8mb4字符集的处理 JDBC驱动默认情况下不支持utf8mb4字符集,如果要…

    Java 2023年6月16日
    00
  • 基于springboot 长轮询的实现操作

    基于Spring Boot长轮询的实现操作 长轮询是一种实现实时通信的技术,它可以在客户端和服务器之间建立一个持久的连接,以便服务器可以在有新数据时立即向客户端推送。在本文中,我们将讲解如何使用Spring Boot实现长轮询,包括两个示例。 示例一:使用Spring WebFlux实现长轮询 Spring WebFlux是Spring Framework …

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