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日

相关文章

  • Java中instanceOf关键字的用法及特性详解

    Java中instanceof关键字的用法及特性详解 什么是instanceof关键字? instanceof是Java中一个二元运算符,用于判断一个对象是否是某个类或其子类的实例。instanceof的语法格式如下: 对象 instanceof 类 其中,对象可以是任何类型的对象,包括基本数据类型,而类则必须是引用类型。如果对象是类或其子类的实例,则返回t…

    Java 2023年5月26日
    00
  • JSONObject toJSONString错误的解决

    当使用Java中的JSONObject类的toJSONString()方法将Java对象序列化为Json字符串时,可能会出现错误。本文将提供一些错误的解决方法。 错误1:No serializer found 当使用toJSONString()方法将Java对象序列化为Json字符串时,可能会出现以下错误: org.codehaus.jackson.map.…

    Java 2023年5月26日
    00
  • Java数据库操作库DButils类的使用方法与实例详解

    Java数据库操作库DButils类的使用方法与实例详解 一、概述 DButils是一款基于Java语言开发的数据库操作库,具有使用简单、功能丰富、高效性等特点。在Java开发中,使用DButils可以让我们更加方便地进行数据库操作,节省我们大量的时间和精力。DButils提供了一组用于执行SQL语句和映射结果集的API,除此之外,还提供了连接池和事务管理等…

    Java 2023年5月19日
    00
  • 详解Spring Boot应用的启动和停止(start启动)

    Spring Boot应用的启动和停止是开发Spring Boot应用的基础,以下是详解Spring Boot应用的启动和停止的完整攻略: 1. Spring Boot应用的启动 Spring Boot应用的启动过程可以分为以下几个步骤: 1.1 加载配置文件 Spring Boot应用启动时会加载application.properties或applica…

    Java 2023年5月14日
    00
  • Java String类详解_动力节点Java学院整理

    Java String类详解 在Java中,String类是一个非常重要的类。本篇文章将对Java String类进行详细的讲解,包括String类的定义、String类的常用方法、String类与其他数据类型的转换以及String类的不可变性等。 String类的定义 在Java中,String类是一个表示字符串的类。每个字符串都是由多个字符组成的字符序列…

    Java 2023年5月26日
    00
  • 常见的Java调试技术有哪些?

    常见的Java调试技术有以下几种: 1.打印日志 打印日志是最简单的调试技术,我们可以将关键信息打印到日志中,用于排查问题。Java提供了日志工具包java.util.logging,在代码中加入以下语句即可打印日志: import java.util.logging.Logger; // 创建Logger实例 private final static Lo…

    Java 2023年5月11日
    00
  • Java中的异步与线程池解读

    Java中的异步与线程池解读 什么是异步? 异步是指一个方法调用不会阻塞当前线程,而是立即返回,然后在另一个线程上执行。由于异步方法不会阻塞当前线程,所以可以提高系统的并发能力,避免系统因等待I/O等操作而造成的阻塞。 在Java中,异步通常是指使用线程池来执行一些耗时的任务。Java 5引入了java.util.concurrent包,其中提供的Excut…

    Java 2023年5月18日
    00
  • SpringBoot启动器Starters使用及原理解析

    SpringBoot启动器Starters使用及原理解析 Spring Boot是一个快速、方便的构建Spring应用程序的框架,它提供了一系列的启动器(Starters)来帮助我们快速引入一些常用的依赖包。Starters的作用就是提供一个快速的方式来导入一个或多个依赖包,它不仅简化了我们的配置过程,还有助于保持我们的应用程序的兼容性和依赖性。 Start…

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