Java中线程池自定义实现详解

Java中线程池自定义实现详解

什么是线程池

在Java中,每次创建线程都需要为该线程分配独立的资源,包括CPU利用时间、栈内存等,这些资源的分配和回收都需要时间开销。当并发任务数量较大时,频繁地创建线程会导致系统负担过重,极有可能会出现OOM等问题。为了解决这个问题,Java提供了线程池,它可以在系统初始化时创建一定数量的线程,并将这些线程保存在池中,执行任务时直接从池中取出线程,并在任务执行完成后归还线程。这种方式可以减少线程创建和销毁的次数,从而提高系统的性能、可靠性和稳定性。

Java自带线程池的工作原理

在Java中,线程池的实现主要通过Executor框架实现。Executor框架定义了执行服务接口Executor、ExecutorService、ScheduledExecutorService和线程工厂接口ThreadFactory。实际上,所有线程池的实现都基于它们。其中,Executor是线程池的根接口,ExecutorService和ScheduledExecutorService是Executor的扩展,而ThreadFactory则是线程创建工厂。下面是一个简单的示例:

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        // 提交任务
        for (int i = 0; i < 10; i++) {
            executorService.submit(new Task());
        }
        // 关闭线程池
        executorService.shutdown();
    }

    static class Task implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is executing task.");
        }
    }
}

自定义线程池的实现

Java中线程池自定义实现需要创建一个实现Executor接口的类,并重写其execute方法,该方法就是线程池执行任务的核心方法,其具体逻辑就是从线程池中获取线程执行任务。以下是一个简单的示例:

public class CustomThreadPool implements Executor {
    private final int poolSize;
    private final BlockingQueue<Runnable> queue;
    private final Thread[] threads;

    public CustomThreadPool(int poolSize, int queueSize) {
        this.poolSize = poolSize;
        this.queue = new ArrayBlockingQueue<>(queueSize);
        this.threads = new Thread[poolSize];

        // 启动线程
        for (int i = 0; i < poolSize; i++) {
            threads[i] = new Thread(new Worker(queue));
            threads[i].start();
        }
    }

    @Override
    public void execute(Runnable command) {
        try {
            queue.put(command);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    static class Worker implements Runnable {
        private final BlockingQueue<Runnable> queue;

        public Worker(BlockingQueue<Runnable> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    queue.take().run();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}

以上代码中,我们创建了一个CustomThreadPool类,它实现了Executor接口,并实现了execute方法。在构造函数中,我们创建了一个大小为poolSize的线程数组threads和一个大小为queueSize的阻塞队列queue。对于queue中的任务,我们创建一个Worker线程从队列中取出并执行。而execute方法就是将任务加入阻塞队列中。

示例1:自定义线程池使用

public class CustomThreadPoolExample1 {
    public static void main(String[] args) {
        CustomThreadPool threadPool = new CustomThreadPool(5, 10);
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Task(i));
        }
    }

    static class Task implements Runnable {
        private final int taskId;

        public Task(int taskId) {
            this.taskId = taskId;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is executing task " + taskId);
        }
    }
}

以上代码中,我们创建了一个大小为5的线程池,并提交了10个任务。可以看到,任务分别由5个线程执行,并且线程执行任务的顺序并不是按照提交的顺序执行的。

示例2:自定义线程池并增加异常处理

public class CustomThreadPoolExample2 {
    public static void main(String[] args) {
        CustomThreadPool threadPool = new CustomThreadPool(5, 10);
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Task(i));
        }
    }

    static class Task implements Runnable {
        private final int taskId;

        public Task(int taskId) {
            this.taskId = taskId;
        }

        @Override
        public void run() {
            try {
                // do something
                System.out.println(Thread.currentThread().getName() + " is executing task " + taskId);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

以上代码中,我们在任务的run方法中增加了异常处理,这样就可以在任务执行时发现问题,并进行相应的处理。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中线程池自定义实现详解 - Python技术站

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

相关文章

  • 微信小程序 ES6Promise.all批量上传文件实现代码

    让我来详细讲解一下“微信小程序 ES6Promise.all批量上传文件实现代码”的攻略过程。 先了解一下Promise.all 在了解如何使用ES6中的Promise.all实现批量上传文件之前,我们先来了解一下Promise.all的相关知识。 Promise.all是一个非常强大的方法,它可以将多个Promise实例包装成一个新的Promise实例。当…

    Java 2023年5月23日
    00
  • Java基础之数组超详细知识总结

    Java基础之数组超详细知识总结 什么是数组 数组(Array)是一种线性表数据结构,它由相同数据类型的多个元素组成,并通过一个索引值来访问每一个元素。在 Java 中,数组也被称为一种特殊的对象。 数组的声明 在 Java 中声明一个数组需要指定数组的类型和数组名,如下所示: // 声明一个 int 类型数组并命名为 array int[] array; …

    Java 2023年5月26日
    00
  • java实现附件预览(openoffice+swftools+flexpaper)实例

    可以分为以下几个步骤来实现Java实现附件预览: 安装OpenOffice OpenOffice是一款免费、开源的办公软件套装,包含字处理、电子表格、演示文稿、数据库等基础应用。我们需要利用OpenOffice来将文档转换为PDF,代码如下: private static void officeToPDF(String sourceFilePath, Str…

    Java 2023年5月20日
    00
  • SpringDataJPA详解增删改查操作方法

    SpringDataJPA详解增删改查操作方法 简介 Spring Data JPA是Spring Framework的一部分,它是JPA规范的一个实现,提供了一种方便、基于注解的方式来实现对数据库的访问和操作。 环境准备 在进行Spring Data JPA的开发之前,我们需要在项目中导入相关的依赖,下面是一个示例的pom.xml配置: <!– S…

    Java 2023年5月20日
    00
  • 利用5分钟快速搭建一个springboot项目的全过程

    下面是详细的攻略过程,包括两个示例。 前置条件 在开始搭建 Spring Boot 项目之前,需要确保以下环境已经安装和配置好: Java JDK 8+,可使用 java -version 命令检查 Java 安装情况。 Maven 3.0+,可使用 mvn -v 命令检查 Maven 安装情况。 IntelliJ IDEA(或其他任意一款 IDE) 步骤一…

    Java 2023年5月15日
    00
  • Java之数组在指定位置插入元素实现

    Java之数组在指定位置插入元素实现 介绍 数组是一种十分常见的数据结构,它用于存储一系列同类型的数据。在Java中,数组是一种对象,也被称为引用类型。数组实际上是只有一个变量名,而其它所有的元素都用一个索引来访问,所以在这个意义上,数组其实就是一个索引表。 在Java中,数组的长度是固定的。一旦创建了一个数组,它的大小就不能被改变了。然而,我们可以通过一些…

    Java 2023年5月26日
    00
  • Java趣味练习题之输出两个日期之间的相隔天数

    以下是对应任务的完整攻略: 标题 题目:Java趣味练习题之输出两个日期之间的相隔天数 题目描述 给定两个日期,请输出两个日期之间相隔的天数。 思路 要求出两个日期之间相隔的天数,我们需要计算两个日期之间的天数差,而计算天数差的核心就是比较两个日期的大小。因此,我们可以将两个日期分别转换成毫秒数,然后通过毫秒数的差值,计算出两个日期之间相隔的天数。 具体实现…

    Java 2023年5月20日
    00
  • 简单了解JAVA构造方法

    简单了解JAVA构造方法 什么是构造方法 Java中每个类都有构造方法,构造方法是用来初始化对象的方法,即在使用new操作符创建对象时调用的一种特殊方法。构造方法与类名相同,无需返回类型,且不能被重载。 构造方法的特点 构造方法名要与类名相同,且区分大小写; 构造方法没有返回值类型; 构造方法没有具体的返回值,但需要使用return语句结束构造方法; 构造方…

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