java实现手写一个简单版的线程池

下面是Java实现手写一个简单版的线程池的完整攻略。

什么是线程池?

线程池是管理线程的一种机制,它可以为任务分配线程、重复利用已创建的线程、控制并发线程数量,从而提高程序的性能和稳定性。

线程池的原理

线程池由一个线程池管理器(ThreadPoolExecutor)和若干个工作线程(Thread)组成。线程池管理器负责线程池的初始化、关闭、提交任务、监控线程池和任务队列等操作。工作线程则负责执行提交的任务。

如何手动实现线程池?

首先,我们需要自定义一个线程池类,该类需要继承 ThreadPoolExecutor 并重写构造器方法,定义线程池的基本参数(核心线程数、最大线程数、空闲线程存活时间、任务队列等),具体详见示例代码:

public class MyThreadPool extends ThreadPoolExecutor {
    public MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    // 执行任务方法
    @Override
    public void execute(Runnable command) {
        super.execute(command);
    }

    // 关闭线程池方法
    @Override
    public void shutdown() {
        super.shutdown();
    }

    // 提交任务方法
    @Override
    public Future<?> submit(Runnable task) {
        return super.submit(task);
    }
}

接着,我们需要编写一个测试类,在测试类中构造自定义的线程池,提交任务,并测试线程池的基本功能,例如:执行任务、关闭线程池等,具体详见示例代码:

public class TestThreadPool {
    public static void main(String[] args) {
        MyThreadPool myThreadPool = new MyThreadPool(5, 10, 200, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory());

        for (int i = 0; i < 20; i++) {
            myThreadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + ": 工作中...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        myThreadPool.shutdown();
    }
}

运行测试类后,我们可以看到线程池在执行任务的过程中,从池中获取线程执行任务,如果线程池中当前可用线程小于核心线程数,则创建新线程执行任务,如果线程池已经达到最大线程数,则将任务添加到工作队列中,等待空闲线程执行,当工作队列满了以后,将新任务拒绝执行。当线程池关闭时,会等待所有任务执行完毕,然后关闭线程池。

案例说明

示例一:启动10个线程执行20个任务

我们构造线程池时,核心线程数为5,最大线程数为10,线程空闲时间为200ms,任务队列为一个无限大的阻塞队列。在测试类中提交20个任务给线程池,从运行结果中可以看到线程池中最多只有10个线程在执行任务,当这10个线程都被占用时,新的任务需要等待空闲线程,等待时间为200ms,如果200ms后仍然没有空闲线程,则将任务添加到工作队列中,等待空闲线程执行。

public class TestThreadPool {
    public static void main(String[] args) {
        MyThreadPool myThreadPool = new MyThreadPool(5, 10, 200, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory());

        for (int i = 0; i < 20; i++) {
            myThreadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + ": 工作中...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        myThreadPool.shutdown();
    }
}

示例二:使用自定义线程池和自定义任务

我们可以自定义线程池和线程池中执行的任务,在测试类中提交自定义任务给自定义线程池执行。

public class MyTask implements Runnable {
    private int taskNum;

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

    @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 MyThreadPool extends ThreadPoolExecutor {
    public MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    // 执行任务方法
    @Override
    public void execute(Runnable command) {
        super.execute(command);
    }

    // 关闭线程池方法
    @Override
    public void shutdown() {
        super.shutdown();
    }

    // 提交任务方法
    @Override
    public Future<?> submit(Runnable task) {
        return super.submit(task);
    }
}

public class TestThreadPool {
    public static void main(String[] args) {
        MyThreadPool myThreadPool = new MyThreadPool(2, 3, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory());

        for (int i = 0; i < 10; i++) {
            myThreadPool.execute(new MyTask(i));
        }

        myThreadPool.shutdown();
    }
}

在上述代码中,我们定义了一个 MyTask 类,实现了 Runnable 接口,并重写了 run 方法。在 MyThreadPool 类中,我们使用了一个 ArrayBlockingQueue 作为任务队列,并重写了线程池类的基本方法。在测试类中,提交了10个自定义任务给自定义线程池执行,我们可以从结果中看到,线程池执行了10个任务。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java实现手写一个简单版的线程池 - Python技术站

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

相关文章

  • java迭代器移除元素出现并发修改异常的原因及解决

    Java迭代器是用于遍历集合类元素的重要工具,然而有时可能会在使用过程中遇到“并发修改异常”(ConcurrentModificationException),指的是在使用迭代器访问集合过程中,通过集合自身的某些方法(如add、remove、clear等)修改了集合元素而导致的异常。本文将讲解这个异常的原因及解决方法,同时会提供两个示例来解释如何在实际操作中…

    Java 2023年5月27日
    00
  • 几道java循环练习题(适合新人)

    首先,对于这篇“几道java循环练习题(适合新人)”文章,它包含了多个练习题,都是基于Java的循环语法实现的。对于初学者来说,可以通过熟悉这些练习题,掌握Java的循环语法。 下面,我们来逐个解析。 第一道题:九九乘法表 这道题要求我们输出九九乘法表。我们可以使用双重循环来实现,外层循环控制行数,内层循环控制列数。 for (int i = 1; i &l…

    Java 2023年5月24日
    00
  • JavaWeb Listener 利用Session统计在线人数

    下面我将详细讲解“JavaWeb Listener 利用Session统计在线人数”的完整攻略。 什么是Listener Listener 是 JavaWeb 中的一种组件,用于监听某一种事件的发生,并在适当的时候做出反应。常用的一些监听器有 ServletContextListener、HttpSessionListener、ServletRequestL…

    Java 2023年6月15日
    00
  • 浅谈Maven Wrapper

    关于如何使用 Maven Wrapper,我这里提供一份完整攻略,包含以下内容: 什么是 Maven Wrapper Maven Wrapper 是 Maven 内置的一个小型 Maven 版本管理工具,是 Maven 3.5.0 版本中引入的新特性。它的主要作用是帮助使用者对 Maven 进行版本控制,防止出现版本不一致的问题。使用 Maven Wrapp…

    Java 2023年6月2日
    00
  • 利用SpringMVC和Ajax实现文件上传功能

    利用SpringMVC和Ajax实现文件上传功能 在 Web 应用程序中,文件上传功能是非常常见的需求。本文将详细讲解如何利用 SpringMVC 和 Ajax 实现文件上传功能,包括如何配置 SpringMVC、如何编写前端代码、如何编写后端代码等,并提供两个示例说明。 配置 SpringMVC 在 SpringMVC 中,我们需要配置 Multipart…

    Java 2023年5月18日
    00
  • Java Servlet异步请求开启的简单步骤

    下面是针对Java Servlet异步请求开启的简单步骤的详细攻略: 1. 确定异步请求的类型 在开发Servlet异步请求前,需要着重考虑请求的类型,以便确定适当的开发方法。异步请求可以分为以下两种类型: 长轮询请求 (Long Polling): 在这种类型的请求中,客户端发送一个请求到服务器,服务器不会立即响应请求。相反,服务器将保持此请求打开,并在数…

    Java 2023年6月15日
    00
  • tomcat虚拟主机_动力节点Java学院整理

    Tomcat虚拟主机 – 动力节点Java学院整理 Tomcat虚拟主机是指在同一台物理服务器上运行多个独立的Tomcat实例,每个Tomcat实例都拥有自己的配置文件、Web应用程序和独立的运行环境。Tomcat虚拟主机技术可以很好地解决多个Web应用程序同时运行、不互相干扰的问题。 过程 1. 修改host文件 首先需要修改hosts文件,将虚拟主机域名…

    Java 2023年6月2日
    00
  • 使用JDBC从数据库中查询数据的方法

    使用JDBC从数据库中查询数据的方法需要经过以下几个步骤: 1. 引入JDBC依赖 使用JDBC需要先引入相应的jar包,常见的JDBC库有MySQL Connector、Oracle JDBC等。以Maven项目为例,可以在pom.xml文件中添加以下Maven依赖: <dependency> <groupId>mysql</…

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