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

yizhihongxing

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 IO流读取图片供前台显示代码分享

    下面是Java IO流读取图片供前台显示的完整攻略: 一、概述 在Java中,使用IO流读取图片供前台显示可以分为以下几个步骤: 使用Java IO流读取图片文件到内存中; 将读取到的图片字节流转换为Base64编码; 将Base64编码的图片数据返回给前台。 二、代码示例 以下是两条示例代码,可以供您参考: 使用FileInputStream和ByteAr…

    Java 2023年5月19日
    00
  • Java Scala数据类型与变量常量及类和对象超详细讲解

    Java Scala数据类型与变量常量及类和对象超详细讲解 一、Java Scala数据类型 在Java Scala中,数据类型主要分为以下几种: 基本数据类型:包括整型、浮点型、布尔型和字符型等。 数组类型:包括一维数组和多维数组。 引用数据类型:包括类类型、接口类型、枚举类型和数组类型等。 下面我们分别对每种数据类型进行详细讲解: 1.1 基本数据类型 …

    Java 2023年5月26日
    00
  • java中String的常见用法总结

    下面我来详细讲解一下Java中String的常见用法总结。 Java中String的常见用法总结 1. 字符串创建 在Java中,可以通过以下三种方式创建字符串: 直接使用字符串字面量创建,例如: java String str1 = “hello world”; 使用String类的构造方法创建: java String str2 = new String…

    Java 2023年5月27日
    00
  • springboot集成开发实现商场秒杀功能

    下面是详细讲解”springboot集成开发实现商场秒杀功能”的完整攻略。 1. 环境搭建 在开始之前,需要先确保你已经安装了以下环境: JDK1.8及以上 Maven3.3及以上 IDE(比如IntelliJ IDEA、Eclipse) 2. 导入依赖 在pom.xml文件中添加以下依赖: <dependency> <groupId&gt…

    Java 2023年5月19日
    00
  • 关于Java利用反射实现动态运行一行或多行代码

    Java反射是指通过运行时借助Java API获取对象信息的机制。反射允许我们在程序运行时动态获取类的相关信息、构造实例、调用方法、访问和修改字段属性等。在一些特殊的需求场景下,我们可以利用Java的反射机制来实现动态运行一行或多行代码。以下是具体实现步骤: 1. 获取指定类的Class对象 在Java中,所有的类都是对象,每个类都有一个Class对象。获取…

    Java 2023年5月26日
    00
  • Spring Boot 底层原理基础深度解析

    Spring Boot 底层原理基础深度解析 Spring Boot 是一款基于 Spring 框架的开发框架,它的出现极大地提高了开发效率。本篇文章将从底层原理入手,对 Spring Boot 的实现机制进行深度解析。 Spring Boot 的核心概念 Spring Boot 的核心概念包括自动装配、起步依赖和 SpringApplication。其中,…

    Java 2023年5月15日
    00
  • JAVA中StackOverflowError错误的解决

    下面是“JAVA中StackOverflowError错误的解决”的完整攻略。 什么是StackOverflowError错误? 在Java程序中,如果方法被递归调用时,方法栈会不断地往系统栈内添加方法栈帧。如果方法递归层数过多,方法栈会撑满,此时就会发生StackOverflowError错误,如下所示: Exception in thread &quot…

    Java 2023年5月27日
    00
  • Java如何实现通过键盘输入一个数组

    Java 可以通过 Scanner 类实现键盘输入一个数组。 具体步骤如下: 引入 Scanner 类 需要使用 java.util 包中的 Scanner 类,因此需要在程序开头声明引入这个包。 import java.util.Scanner; 定义 Scanner 对象 在程序中定义一个 Scanner 对象用于读取键盘输入: Scanner sc =…

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