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日

相关文章

  • windows tomcat配置大全[详细]

    关于“windows tomcat配置大全[详细]”,我将为你提供一份完整攻略,主要分为以下几个步骤: 1. 下载和安装Tomcat 首先,你需要前往Tomcat的官方网站(https://tomcat.apache.org/)下载并安装Tomcat。 2. 配置Tomcat环境变量 为了使Tomcat在任何目录下都可以访问,你需要将Tomcat的安装路径添…

    Java 2023年5月19日
    00
  • centos 安装java环境的多种方法

    CentOS 安装 Java 环境的多种方法 Java 是一种跨平台、面向对象的编程语言,广泛应用于 Web 开发、移动开发和桌面应用开发等领域。但是,在运行 Java 程序之前必须先安装 Java 运行环境(JRE)或 Java 开发工具包(JDK)。本文将介绍 CentOS 安装 Java 环境的多种方法。 方法一:通过 yum 命令安装 CentOS …

    Java 2023年5月24日
    00
  • Lambda表达式的使用及注意事项

    Lambda表达式是Java8新引入的一种语法形式,可以用于简洁地定义匿名函数,常用于对集合进行筛选、映射等操作。下面将详细讲解Lambda表达式的使用及注意事项。 Lambda表达式的语法 Lambda表达式由三部分组成:参数列表、箭头符号和表达式或语句块。其基本格式为: (参数列表) -> {表达式或语句块} 例如,下面是一个Lambda表达式的例…

    Java 2023年5月19日
    00
  • 一篇文章带你入门java方法

    一篇文章带你入门Java方法的完整攻略 Java方法是一段可重用的代码块,可以在程序中多次调用,帮助我们拆分复杂的业务逻辑。在本文中,我们将介绍Java方法的基础知识,包括方法的定义、调用和参数传递。 1. 方法的定义 Java方法由以下几个部分组成: 访问修饰符:public、protected、private或默认(不写)。 返回值类型:方法执行完毕后返…

    Java 2023年5月30日
    00
  • FP-growth算法发现频繁项集——发现频繁项集

    FP-growth算法发现频繁项集——发现频繁项集 什么是频繁项集? 在数据挖掘中,频繁项集(Frequent Itemset)指在一个数据集中经常出现在一起的项的集合,常用于关联规则挖掘。例如,在超市的交易记录中,若苹果和香蕉经常一起被购买,则{苹果,香蕉}是一个频繁项集。 什么是FP-growth算法? FP-growth算法是一种用于挖掘数据中的频繁项…

    Java 2023年5月19日
    00
  • 使用dynamic datasource springboot starter实现多数据源及源码分析

    下面我们来详细讲解使用dynamic datasource springboot starter实现多数据源及源码分析的完整攻略。 什么是dynamic datasource springboot starter? dynamic datasource springboot starter是一款基于spring boot的多数据源解决方案,可以支持动态添加和…

    Java 2023年5月20日
    00
  • 详解spring与shiro集成

    对于“详解spring与shiro集成”的完整攻略,我可以提供以下步骤和代码示例供参考: 1. 添加shiro依赖 在项目的pom文件中,添加shiro的依赖: <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</…

    Java 2023年5月20日
    00
  • Java8常用的新特性详解

    Java8常用的新特性详解 Java8是Java语言的一个重大升级,带来了很多新特性。本文将会详细讲解Java8中常用的新特性,方便读者更好地掌握和使用Java8。 Lambda表达式 Lambda表达式是Java8中引入的一项重要特性。它可以用来替代Java中的匿名内部类,并且更加简洁明了。Lambda表达式的语法非常简单,格式如下: (parameter…

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