Java实现手写线程池实例并测试详解

前言

在之前的文章中介绍过线程池的核心原理,在一次面试中面试官让手写线程池,这块知识忘记的差不多了,因此本篇文章做一个回顾。

希望能够加深自己的印象以及帮助到其他的小伙伴儿们

在线程池核心原理篇介绍过线程池的核心原理,今天来模拟线程池和工作队列的流程,以及编写代码和测试类进行测试。下面附下之前线程池的核心流程:

在线程池核心原理的源码中,涉及到了一系列的流程,包括线程池队列数量是否已满,运用什么样的拒绝策略等。在我们手写线程池的代码中,不需要考虑那么多因素,只需要模拟简单的情景和过程,因此整体来讲还是比较简单的。

手写线程池,必不可少的组件有任务队列,任务的消费者线程池,线程池创建等。我们也可定义构造方法,创建指定大小的线程池线程个数。当然在使用完线程池中的线程后,我们需要考虑将其销毁或关闭。

相关代码和解释如下:

package XIAOWEI;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.IntStream;

public class ThreadPool {
    private static final int WorkQueueSIZE = 5;
    private BlockingQueue<Runnable> workQueue;
    private List<WorkThread> workThreads=new ArrayList<WorkThread>();

    /**
     * @author xiaowei
     * @param poolSize
     * @param workQueue
     * 构造方法,传线程池的大小和阻塞队列
     */
    public ThreadPool(int poolSize,BlockingQueue<Runnable> workQueue) {
        this.workQueue = workQueue;
        IntStream.range(0,poolSize).forEach((i)->{
            WorkThread workThread=new WorkThread();
            workThread.start();
            workThreads.add(workThread);
        });
    }

    /**
     * @param poolSize
     * 在ThreadPool的构造方法中传入线程池的大小
     */
    public ThreadPool(int poolSize){
        this(poolSize,new LinkedBlockingQueue<>(WorkQueueSIZE));
    }

    /**
     * @param task
     * 通过线程池执行任务
     */
    public void extcute(Runnable task){
        try {
            workQueue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void shutdown(){
        if(workThreads!=null && workThreads.size()>0){
            workThreads.stream().forEach((workThread) -> {
                workThread.interrupt();
            });
        }
    }
    /**
     * 内部类 源源不断的消耗workQueue中的任务
     */
    class WorkThread extends Thread {
        @Override
        public void run() {
            Thread currentThread = Thread.currentThread();
            // 死循环 不断一直消费队列中的任务 直到任务被消费完全
            while (true) {
                try {
                    if (currentThread.isInterrupted()) {
                        break;
                    }
                    Runnable workTasK = workQueue.take();
                    workTasK.run();
                } catch (InterruptedException e) {
                    currentThread.interrupt();
                }
            }
        }
    }
}

相关测试代码如下:

package XIAOWEI;

import java.util.stream.IntStream;

public class ThreadPoolTest {
    public static void main(String[] args) {
        ThreadPool threadPool = new ThreadPool(5);
        IntStream.range(0,10).forEach((i)->{
            threadPool.extcute(()->{
                System.out.println(Thread.currentThread().getName()+"2023一起加油");
            });
        });
        threadPool.shutdown();
    }
}

一共在线程池中加入了五个线程和十个任务,因此每个线程会执行两个任务。

测试结果如下图所示:

以上就是Java实现手写线程池实例并测试详解的详细内容,更多关于Java手写线程池的资料请关注我们其它相关文章!

(0)

相关推荐

  • 一文带你弄懂Java中线程池的原理

    目录 为什么要用线程池 线程池的原理 ThreadPoolExecutor提供的构造方法 ThreadPoolExecutor的策略 线程池主要的任务处理流程 ThreadPoolExecutor如何做到线程复用的 四种常见的线程池 newCachedThreadPool newFixedThreadPool newSingleThreadExecutor newScheduledThreadPool 小结 在工作中,我们经常使用线程池,但是你真的了解线程池的原理吗?同时,线程池工作原理和底层实

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

    目录 前言 线程为什么不能多次调用start方法 线程池到底是如何复用的 前言 最初使用线程池的时候,网上的文章告诉我说线程池可以线程复用,提高线程的创建效率.从此我的脑海中便为线程池打上了一个标签——线程池可以做到线程的复用.但是我总以为线程的复用是指在创建出来的线程可以多次的更换run()方法的内容,来达到线程复用的目的,于是我尝试了一下.同一个线程调用多次,然后使run的内容不一样,但是我发现我错了,一个线程第一次运行是没问题的,当再次调用start方法是会抛出异常(java.lang.I

  • Java动态线程池插件dynamic-tp集成过程浅析

    目录 前言 快速开始 监控数据和第三方平台对接 logging方式 MicroMeter方式 总结 前言 dynamic-tp是一个轻量级的动态线程池插件,它是一个基于配置中心的动态线程池,线程池的参数可以通过配置中心配置进行动态的修改,目前支持的配置中心有Apollo,Nacos和Zookeeper,同时dynamic-tp支持线程池的监控和报警,具体特性如下: 基于Spring框架,现只支持SpringBoot项目使用,轻量级,引入 starter 即可使用 基于配置中心实现线程池参数动态调

  • Java动态线程池插件dynamic-tp集成zookeeper

    目录 前言 配置刷新 Zookeeper配置中心接入扩展实现 总结 前言 dynamic-tp是一个轻量级的动态线程池插件,它是一个基于配置中心的动态线程池,线程池的参数可以通过配置中心配置进行动态的修改,在配置中心的支持上最开始的时候支持Nacos和Apollo,由于笔者公司用的配置中心是Zookeeper,所以就想着扩展支持Zookeeper,在了解源码支持发现dynamic-tp的扩展能力做的很好,提供了扩展接口,只要我开发对应的配置中心模块即可,最终笔者实现了Zookeeper的支持并贡

  • Java实现手写线程池实例并测试详解

    前言 在之前的文章中介绍过线程池的核心原理,在一次面试中面试官让手写线程池,这块知识忘记的差不多了,因此本篇文章做一个回顾. 希望能够加深自己的印象以及帮助到其他的小伙伴儿们 在线程池核心原理篇介绍过线程池的核心原理,今天来模拟线程池和工作队列的流程,以及编写代码和测试类进行测试.下面附下之前线程池的核心流程: 在线程池核心原理的源码中,涉及到了一系列的流程,包括线程池队列数量是否已满,运用什么样的拒绝策略等.在我们手写线程池的代码中,不需要考虑那么多因素,只需要模拟简单的情景和过程,因此整体来

  • Java实现手写线程池的示例代码

    目录 前言 线程池给我们提供的功能 工具介绍 Worker设计 线程池设计 总结 前言 在我们的日常的编程当中,并发是始终离不开的主题,而在并发多线程当中,线程池又是一个不可规避的问题.多线程可以提高我们并发程序的效率,可以让我们不去频繁的申请和释放线程,这是一个很大的花销,而在线程池当中就不需要去频繁的申请线程,他的主要原理是申请完线程之后并不中断,而是不断的去队列当中领取任务,然后执行,反复这样的操作.在本篇文章当中我们主要是介绍线程池的原理,因此我们会自己写一个非常非常简单的线程池,主要帮

  • java并发编程_线程池的使用方法(详解)

    一.任务和执行策略之间的隐性耦合 Executor可以将任务的提交和任务的执行策略解耦 只有任务是同类型的且执行时间差别不大,才能发挥最大性能,否则,如将一些耗时长的任务和耗时短的任务放在一个线程池,除非线程池很大,否则会造成死锁等问题 1.线程饥饿死锁 类似于:将两个任务提交给一个单线程池,且两个任务之间相互依赖,一个任务等待另一个任务,则会发生死锁:表现为池不够 定义:某个任务必须等待池中其他任务的运行结果,有可能发生饥饿死锁 2.线程池大小 注意:线程池的大小还受其他的限制,如其他资源池:

  • Java中四种线程池的使用示例详解

    在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.将需处理的任务的数量大 使用线程池的好处: 1.减少在创建和销毁线程上所花的时间以及系统资源的开销 2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及"过度切换". 本文详细的给大家介绍了关于Java中四种线程池的使用,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: FixedThreadPool 由Executors的newFixedThreadPool方法创建.它是一种线程数量固定的线程

  • Java手写线程池的实现方法

    本文实例为大家分享了Java手写线程池的实现代码,供大家参考,具体内容如下 1.线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程. 2.线程池简易架构 3.简易线程池代码(自行优化) import java.util.List; /** * 线程接口 * * @Author yjian * @Date 14:49 2017/10/14 **/ public interface IThreadPool { //加入任务 void ex

  • Java手写线程池之向JDK线程池进发

    目录 前言 JDK线程池一瞥 自己动手实现线程池 线程池参数介绍 实现Runnable 实现Callable 拒绝策略的实现 线程池关闭实现 工作线程的工作实现 线程池实现的BUG 完整代码 线程池测试 总结 前言 在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池非常相似的线程池. JDK线程池一瞥 我们首先看一个JDK给我们提供的线程池ThreadPoolExecutor的构造函数的参数:

  • Java线程池FutureTask实现原理详解

    前言 线程池可以并发执行多个任务,有些时候,我们可能想要跟踪任务的执行结果,甚至在一定时间内,如果任务没有执行完成,我们可能还想要取消任务的执行,为了支持这一特性,ThreadPoolExecutor提供了 FutureTask 用于追踪任务的执行和取消.本篇介绍FutureTask的实现原理. 类视图 为了更好的理解FutureTask的实现原理,这里先提供几个重要接口和类的结构,如下图所示: RunnableAdapter ThreadPoolExecutor提供了submit接口用于提交任

  • java 可重启线程及线程池类的设计(详解)

    了解JAVA多线程编程的人都知道,要产生一个线程有两种方法,一是类直接继承Thread类并实现其run()方法:二是类实现Runnable接口并实现其run()方法,然后新建一个以该类为构造方法参数的Thread,类似于如下形式: Thread t=new Thread(myRunnable).而最终使线程启动都是执行Thread类的start()方法. 在JAVA中,一个线程一旦运行完毕,即执行完其run()方法,就不可以重新启动了.此时这个线程对象也便成了无用对象,等待垃圾回收器的回收.下次

  • Java多线程之线程池七个参数详解

    ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交.线程管理.监控等方法. 下面是ThreadPoolExecutor类的构造方法源码,其他创建线程池的方法最终都会导向这个构造方法,共有7个参数:corePoolSize.maximumPoolSize.keepAliveTime.unit.workQueue.threadFactory.handler. public ThreadPoolExecutor(int corePoolS

  • Java 线程池全面总结与详解

    目录 原理 阻塞队列 有界阻塞队列 无界阻塞队列 同步移交队列 实现类分析 使用Executors创建线程池 线程池关闭 线程池是很常用的并发框架,几乎所有需要异步和并发处理任务的程序都可用到线程池. 使用线程池的好处如下: 降低资源消耗:可重复利用已创建的线程池,降低创建和销毁带来的消耗: 提高响应速度:任务到达时,可立即执行,无需等待线程创建: 提高线程的可管理性:线程池可对线程统一分配.调优和监控. 原理 线程池的原理非常简单,这里用处理流程来概括: 线程池判断核心池里的线程是否都在执行任

随机推荐