java多线程学习笔记之自定义线程池

Java多线程学习笔记之自定义线程池

什么是线程池

线程池是管理线程的一种机制。在Java中,可以通过Executor接口及其实现类来创建线程池。线程池的主要作用是优化线程的创建和运行过程。通过创建线程池,可以减少线程创建的开销,并且可以更好地控制线程的运行状态。

创建线程池

基本使用

Java中提供了四种线程池的实现类,它们分别为:

  • newFixedThreadPool(int n):创建一个固定大小的线程池,即线程数量为n个。
  • newCachedThreadPool():创建一个大小不固定的线程池,根据需要创建新的线程。
  • newSingleThreadExecutor():创建一个只有一个线程的线程池。
  • newScheduledThreadPool(int n):创建一个固定大小的线程池,并且支持定时执行任务。

以上四种线程池都位于java.util.concurrent.Executors类中。

下面是一个基本的使用示例,使用newFixedThreadPool方法创建固定大小的线程池:

ExecutorService executorService = Executors.newFixedThreadPool(3);

以上代码创建了一个线程数量为3的固定大小的线程池。

自定义线程池

除了上述的四种线程池以外,我们还可以通过ThreadPoolExecutor类来自定义线程池。

ThreadPoolExecutor类的构造方法如下:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

参数说明:

  • corePoolSize:线程池中的常驻线程数量。
  • maximumPoolSize:线程池的最大线程数量。
  • keepAliveTime:线程池中空闲线程的存活时间。
  • unit:存活时间的时间单位。
  • workQueue:任务队列。
  • threadFactory:线程工厂。
  • handler:任务拒绝策略。

下面是一个自定义线程池的示例:

public class MyThreadPool {
    private final ThreadPoolExecutor executor;

    public MyThreadPool() {
        int corePoolSize = 2;
        int maximumPoolSize = 5;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(5);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    public void execute(Runnable task) {
        executor.execute(task);
    }

    public void shutdown() {
        executor.shutdown();
    }
}

以上代码中,我们自定义了一个线程池MyThreadPool,并且设置了线程池中常驻线程数量为2个,最大线程数量为5个。空闲线程的存活时间为10秒钟,任务队列使用了ArrayBlockingQueue,大小为5。

线程池的使用

我们可以通过execute方法来向线程池中提交一个任务:

executorService.execute(new MyTask());

其中,MyTask是一个实现了Runnable接口的任务对象。

除此之外,我们还可以通过submit方法来向线程池中提交一个任务,并且可以获取到该任务的执行结果:

Future<String> future = executorService.submit(new MyCallable());
String result = future.get();

其中,MyCallable是一个实现了Callable接口的任务对象,并且可以返回一个String类型的结果。

任务拒绝策略

当线程池已满,不能再接受新的任务时,我们可以通过设置RejectedExecutionHandler来指定任务的拒绝策略。ThreadPoolExecutor提供了四种默认的拒绝策略:

  • AbortPolicy:直接丢弃任务,并抛出一个RejectedExecutionException异常。
  • CallerRunsPolicy:由调用线程来执行此任务。
  • DiscardOldestPolicy:直接丢弃最早提交的任务。
  • DiscardPolicy:直接丢弃当前提交的任务。

除此之外,我们还可以通过自定义RejectedExecutionHandler来实现自己的任务拒绝策略。

示例1:固定大小线程池的使用

// 创建一个固定大小线程池,线程数量为3个
ExecutorService executorService = Executors.newFixedThreadPool(3);

// 提交10个任务
for (int i = 0; i < 10; i++) {
    executorService.execute(new MyTask(i));
}

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

以上代码创建了一个线程池,大小为3个。我们向线程池中提交了10个任务,并且在执行完成后关闭了线程池。其中,MyTask是一个实现了Runnable接口的任务对象。

示例2:自定义线程池

public class MyTask implements Runnable {
    private int taskNum;

    public MyTask(int taskNum) {
        this.taskNum = taskNum;
    }

    @Override
    public void run() {
        System.out.println("正在执行task " + taskNum);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("task " + taskNum + " 执行完毕");
    }
}

public class TestMyThreadPool {
    public static void main(String[] args) {
        MyThreadPool threadPool = new MyThreadPool();

        // 提交10个任务
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new MyTask(i));
        }

        // 关闭线程池
        threadPool.shutdown();
    }
}

以上代码自定义了一个线程池MyThreadPool,我们向线程池中提交了10个任务,并且在执行完成后关闭了线程池。其中,MyTask是一个实现了Runnable接口的任务对象。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java多线程学习笔记之自定义线程池 - Python技术站

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

相关文章

  • JAVA十大排序算法之希尔排序详解

    JAVA十大排序算法之希尔排序详解 什么是希尔排序? 希尔排序,也称为“缩小增量排序”,是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort)。希尔排序将数组所有元素划分为若干个区域,然后分别对每一个区域使用直接插入排序算法进行排序。随着排序的进行,它会不断缩小区域的范围,直到整个数组被作为一个区域处理。 希尔排序的优点…

    Java 2023年5月19日
    00
  • java字节字符转换流操作详解

    Java字节字符转换流操作详解 什么是Java字节字符转换流? Java字节字符转换流是Java I/O API中的一种高级流(也叫过滤流或处理流),用于在字节流和字符流之间进行转换。在Java中,通常使用字节流来处理二进制数据文件、图像文件和音频文件等等,而使用字符流来处理文本文件。但是在实际开发中,我们可能需要将字节流转换成字符流或将字符流转换成字节流。…

    Java 2023年5月20日
    00
  • JAVA中数组插入与删除指定元素的实例代码

    下面是针对“JAVA中数组插入与删除指定元素的实例代码”的完整攻略: 一、JAVA数组插入指定元素 在JAVA中,数组的长度是固定的,所以如果需要在数组中插入元素,我们必须新建一个长度为原数组长度+1的新数组,并将原数组中的元素复制到新数组中,在新数组中插入指定元素。 以下是一个示例代码,用于将指定元素插入到数组的指定位置: public class Arr…

    Java 2023年5月26日
    00
  • Java事务管理学习之Hibernate详解

    Java事务管理学习之Hibernate详解攻略 一、什么是Hibernate? Hibernate是一个开源的ORM(Object-Relational Mapping)框架,它将Java对象映射到数据库表中,从而实现Java应用程序和数据库的交互。Hibernate的优点在于它轻松地处理复杂的数据库操作,可以帮助开发人员轻松地执行增删查改等操作。 二、如…

    Java 2023年5月19日
    00
  • Android简易图片浏览器的实现

    下面是关于“Android简易图片浏览器的实现”的完整攻略: 1. 实现概述 首先,在构建这个简易图片浏览器时,我们需要考虑几个方面:界面设计、数据加载以及图片缓存等。因此,我们可以将实现分为以下几个步骤: 界面设计:该步骤主要是实现图片的展示,并提供一系列操作,如滑动查看、保存等。我们可以使用ViewPager进行实现。 数据加载:该步骤主要是加载图片资源…

    Java 2023年5月23日
    00
  • Java 配置加载机制详解及实例

    Java 配置加载机制详解及实例 在 Java 中,配置文件被广泛用于存储应用程序的配置信息。应用程序在启动时需要读取配置文件并使用其中的参数。如果你使用 Java 编写应用程序,你需要掌握 Java 中的配置文件的加载机制。 配置文件的加载机制 Java 中的配置文件可以使用多种格式,如 .properties、.xml、.json 等。在加载配置文件时,…

    Java 2023年6月2日
    00
  • JAVA异常处理机制之throws/throw使用情况

    JAVA异常处理机制之throws/throw使用情况 在 Java 中,异常处理是一个非常重要的主题,Java 异常的设计是基于类层次结构的。在 Java 中,所有异常的根源是 Throwable 类。Throwable 类有两个子类:Error 和 Exception,其中 Error 一般为虚拟机错误,一般是程序员无法解决的错误。而 Exception…

    Java 2023年5月27日
    00
  • java代码实现银行管理系统

    Java代码实现银行管理系统攻略 银行管理系统是一个较为复杂的系统,包含了许多业务、功能和数据操作,但使用Java语言实现银行管理系统也不是难事。在本文中,我将通过以下步骤详细讲解如何使用Java代码实现银行管理系统。 第一步:分析业务需求 在编写Java代码之前,我们首先需要了解银行管理系统的业务需求。常见的银行管理系统包括账户管理、存取款、贷款管理、利率…

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