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实战之实现一个好用的MybatisPlus代码生成器

    首先需要明确的是,MybatisPlus是Mybatis的一个增强版本,能够大大提高开发效率。而MybatisPlus代码生成器能够自动生成基本的CRUD操作,这对于快速搭建项目是非常有帮助的。下面我将详细讲解如何实现一个好用的MybatisPlus代码生成器。 准备工作 添加MybatisPlus及其依赖到项目中。 创建数据库及数据表。(以下示例中,我们使…

    Java 2023年5月19日
    00
  • SpringSecurity数据库进行认证和授权的使用

    SpringSecurity是一个专门用于处理应用程序安全认证和授权的框架。它提供了一系列的功能能够让我们轻松地实现基于角色、基于资源的权限控制。为了实现安全认证和授权,SpringSecurity可以使用多种数据源,其中最常用的是数据库。在本篇文章中,我将会详细讲解如何使用数据库进行SpringSecurity的认证和授权,包括以下内容: 导入相关依赖 在…

    Java 2023年5月20日
    00
  • JAVA基于SnakeYAML实现解析与序列化YAML

    下面就是“JAVA基于SnakeYAML实现解析与序列化YAML”的完整攻略。 什么是YAML? YAML是一种轻量级的数据交换格式,它特别适合于人类编辑或查看。与JSON、XML等数据格式相比,它更为简洁、易于理解和编写,而且可以支持嵌套的数据结构。 SnakeYAML是什么? SnakeYAML是一个Java库,提供对YAML的解析和生成。通过Snake…

    Java 2023年5月26日
    00
  • java基础的详细了解第九天

    Java基础的详细了解第九天的攻略如下: 一、集合框架 集合框架是Java中非常重要的一部分内容,也是开发Java应用程序必不可少的一部分。集合框架主要由三个接口和13个类组成,我们需要熟练掌握各个类的使用方法,包括:ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap 等。 1. ArrayList Ar…

    Java 2023年5月26日
    00
  • XML与HTML的结合(上)

    下面我来为您详细讲解“XML与HTML的结合(上)”的完整攻略。 首先,让我们先明确一下XML和HTML的区别。HTML(Hypertext Markup Language)是一种用于创建网页的标记语言,而XML(Extensible Markup Language)则是一种通用的标记语言,用于描述数据。 因为XML具有更加灵活的结构和语法,所以可以用来描述…

    Java 2023年5月23日
    00
  • 关于JAVA 数组的使用介绍

    关于Java数组的使用介绍 Java中的数组是一种非常常见的数据结构,可以容纳同一种数据类型(可以是基本类型或对象类型)的固定数量的元素。本文将介绍Java数组的基本用法,包括声明、初始化、访问以及一些常见的操作和示例。 数组的声明和初始化 Java声明一个数组需要指定数组名称、数组元素的类型和数组的大小,数组元素的类型可以是Java中的任意数据类型(例如,…

    Java 2023年5月26日
    00
  • Spring Boot日志的打印与持久化详细解析

    Spring Boot日志的打印与持久化详细解析 在Spring Boot应用中,日志是开发和调试的重要工具。通过合理的配置,我们可以实现日志的打印和持久化,方便问题的排查和解决。本文将详细介绍Spring Boot日志的打印与持久化,并包含两条示例。 Spring Boot日志的分类 Spring Boot日志分为如下五个级别: TRACE:跟踪级别,最低…

    Java 2023年5月19日
    00
  • Java开发中POJO和JSON互转时如何忽略隐藏字段的问题

    Java开发中POJO(Plain Old Java Object,简单Java对象)和JSON(JavaScript Object Notation,JavaScript对象表示法)的相互转换是非常常见的操作。但在转换过程中,可能会遇到一些字段需要被隐藏的情况,例如:密码字段、某些敏感信息等。这时候,就需要对转换过程进行忽略操作。 下面是一些处理Java开…

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