java多线程学习6:自己实现一个线程池

【多线程】实现一个线程池 本期主要讲解: 1.线程池的概念 1.1什么是线程池? 1.2为什么需要线程池? 2.Java标准库自带的线程池 2.1工厂模式 2.2简单使用线程池 3.常见创建线程池的方法 4.ThreadPoolExecutor类 4.1构造方法 4.2拒绝策略 5.实现一个简单的线程池 阅读详情

线程池需要哪些元素:
1、任务队列,做任务的异步提交
2、核心线程数、最大线程数
3、拒绝策略
4、线程工厂

基本上的思路就是,任务队列提交任务,线程通过任务队列获取任务。
任务队列堆积新增工作线程,定期检测活跃线程。 任务满了,提供拒绝策略

下面是一个简单的实现:

package com.puqiuyu.thread.blog;
/**
 * 实现一个线程池要哪些东西
 * 1、任务队列,做异步提交
 * 2、核心线程池、最大线程池
 * 3、拒绝策略
 * @author sunday
 *
 */

import java.util.Iterator;
import java.util.LinkedList;

public class SimpleThreadPool {

    private final int INIT_SIZE;

    private final static int DEFAULT_SIZE = 10;

    private final Object MONITOR = new Object();

    private final LinkedList<Runnable> TASK_QUEUE = new LinkedList<>();

    private final int MAX_QUEUE_SIZE;

    private final static int DEFUALT_QUEUE_SIZE = 50;

    private final LinkedList<WorkerThread> WORKERS = new LinkedList<>();

    private final int MAX_POOL_SIZE;

    private final static int DEFAULT_MAX_SIZE = Integer.MAX_VALUE;

    private final RecycleThread recycleThread;

    public SimpleThreadPool() {
        this(DEFAULT_SIZE, DEFAULT_MAX_SIZE, DEFUALT_QUEUE_SIZE);
    }

    public SimpleThreadPool(int core, int max, int task) {
        this.INIT_SIZE = core;
        this.MAX_POOL_SIZE = max;
        this.MAX_QUEUE_SIZE = task;
        init();
        recycleThread = new RecycleThread();
        recycleThread.start();
    }

    private void init() {
        for (int i = 0; i < INIT_SIZE; i++) {
            createWorkerThread();
        }
    }

    private void createWorkerThread() {
        WorkerThread thread = new WorkerThread();
        WORKERS.addLast(thread);
    }

    public void submit(Runnable runnable) {
        synchronized (MONITOR) {
            // task_queue not empty 说明 线程不够了
            if (!TASK_QUEUE.isEmpty() && TASK_QUEUE.size() < MAX_POOL_SIZE) {
                createWorkerThread();
            }
            if (TASK_QUEUE.size() < MAX_QUEUE_SIZE) {
                TASK_QUEUE.addLast(runnable);
                MONITOR.notifyAll();
            }
        }
        // discard policy
    }

    public void shutdown() throws InterruptedException {
        while (!TASK_QUEUE.isEmpty()) {
            Thread.sleep(50);
        }
        synchronized (MONITOR) {
            for (WorkerThread workerThread : WORKERS) {
                while (workerThread.status != ThreadStatus.DEAD) {
                    if (workerThread.status == ThreadStatus.BLOCKED) {
                        workerThread.interrupt();
                        workerThread.close();
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            recycleThread.interrupt();
            recycleThread.close();
        }
    }

    //工作线程 获取任务执行
    private class WorkerThread extends Thread {
        ThreadStatus status = ThreadStatus.FREE;

        @Override
        public void run() {
            outer: while (status != ThreadStatus.DEAD) {

                Runnable runnable = null;
                synchronized (MONITOR) {
                    while (TASK_QUEUE.size() <= 0) {
                        status = ThreadStatus.BLOCKED;
                        try {
                            MONITOR.wait();
                        } catch (InterruptedException e) {
                            continue outer;
                        }
                    }
                    status = ThreadStatus.RUNNING;
                    runnable = TASK_QUEUE.removeFirst();
                }
                if (runnable != null) {
                    status = ThreadStatus.RUNNING;
                    runnable.run();
                    status = ThreadStatus.FREE;
                }
            }
        }

        private void close() {
            this.status = ThreadStatus.DEAD;
        }
    }

    private enum ThreadStatus {
        FREE, RUNNING, BLOCKED, DEAD;
    }

    // 空闲时回收线程
    private class RecycleThread extends Thread {
        private boolean closed = false;

        @Override
        public void run() {
            while (!closed) {
                synchronized (MONITOR) {
                    if (TASK_QUEUE.isEmpty() && WORKERS.size() > INIT_SIZE) {// 任务队列空,工作队列大于核心线程数
                        int release = WORKERS.size() - INIT_SIZE;
                        for (Iterator<WorkerThread> iterator = WORKERS.iterator(); iterator.hasNext();) {
                            if (release == 0)
                                break;
                            WorkerThread thread = iterator.next();
                            if (thread.status == ThreadStatus.BLOCKED) {
                                thread.interrupt();
                                thread.close();
                                iterator.remove();
                                release--;
                            }
                        }
                    }
                }
                try {
                    Thread.sleep(5_000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void close() {
            closed = true;
        }
    }
}
【Java 多线程 2】java线程池原理 一、线程池的优势 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗; 提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行; 方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换(cpu切换线程是有时间成本的(需要保持当前执行线程的现场,并恢复要执行线程的现场))。 提供更强大的功能,延时定时线程池。 二、线程池主要方法 public ThreadPoolExecutor(int co 阅读详情

相关推荐

java 线程池示例(自己实现的参考别人的代码)

NULL 博文链接:https://yulincqupt.iteye.com/blog/1673919

自己实现一个简单的线程池

自己实现一个简单的线程池 介绍 当使用多线程的时候频繁的创建销毁线程是比较耗费系统资源,这个时候就需要使用线程池来管理减少资源的开销。在某站学习过后,决定自己也写一个简单的线程池,来加深印象。 线程池中肯定需要有一个等待队列,里面存入相关的任务。然后每次从里面取出任务执行,继续往队列里添加任务。在这个过程中可能任务处理的时间比较长,存或取这个过程就需要添加超时时间,不然一直会阻塞等待。 任务队列 基础属性 /** * 任务队列 */ private final Deque<T> queue

Always`的博客 1014

Java 自己实现线程池

Java开发,Android开发,自己实现线程池,明白线程池的实现机制

自己动手写一个线程池

问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写的线程池如何测试? 简介 线程池是Java并发编程中经常使用到的技术,那么自己如何动手写一个线程池呢?本文彤哥将手把手带你写一个可用的线程池。 属性分析 线程池,顾名思义它首先是一个“池”,这个池里面放的是线程,线程是用来执行任务的。 首先,线程池中的线程应该是有类别的,有的是核心线程,有的是非核心线程,所以我们需要两个变量标识核心线程数量coreSize和最大线程数量maxSize。 为什么要区分是否为核心线程呢?这是为了

qq_52467117的博客 1658

STM32F4的sct文件理解

原文地址http://blog.sina.com.cn/s/blog_898f36590100ya2l.html ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...

weixin_34008805的博客 995

新手避坑指南:用Silvaco Atlas搞定GaN HEMT电热仿真的完整流程(附代码解读)

本文详细介绍了使用Silvaco Atlas进行GaN HEMT电热特性仿真的完整流程,特别针对新手常见问题提供避坑指南。从软件环境配置、结构定义、网格划分到物理模型设置,逐步解析关键步骤,并附有代码解读和调试技巧,帮助读者快速掌握GaN器件仿真的核心技术。

weixin_29215815的博客 597

自己动手写线程池——向JDK线程池进发

在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池非常相似的线程池。// 当前在执行任务的线程个数 |||||||| | ||| | |||| | |ct:表示当前线程池当中线程的个数。corePoolSize:线程池当中核心线程的个数,意义和上面谈到的JDK的线程池意义一致。maximumPoolSize:线程池当中最大的线程个数,意义和上面谈到的JDK的线程池意义一致。

「 虚幻私塾」 564

保姆级教程:在Ubuntu 22.04上搞定PX4 V1.14 + ROS2 Humble的HITL仿真(避坑实录)

本文提供在Ubuntu 22.04上配置PX4 V1.14与ROS2 Humble的HITL仿真环境的详细教程,涵盖环境准备、固件编译、QGroundControl配置、ROS2通信设置及联调测试。特别针对版本兼容性、Gazebo插件构建和MicroDDS配置等常见问题提供避坑指南,帮助开发者高效搭建无人机仿真系统。

weixin_30836759的博客 1005

实现自定义线程池

尝试着自己写一个线程池加深对JDK线程池的理解,从阻塞队列出发,协调任务的产生与线程池消费任务,用ReentrantLock锁技术,对阻塞队列是否已满,为空等情况进行阻塞挂起线程;再设计线程池,围绕任务的执行execute,与队列实现一些拒绝策略等等

Sumuxi9797926的博客 1161

告别CAPL编程!用Matlab/Simulink+CANoe实现复杂ECU仿真的5个技巧

本文介绍了如何利用Matlab/Simulink与CANoe进行联合仿真,以替代复杂的CAPL编程,高效实现复杂ECU仿真。文章分享了5个核心技巧,涵盖信号映射、模型编译集成、实时参数调整、性能优化及数据分析,帮助算法工程师构建稳定强大的仿真环境,显著提升开发与测试效率。

rgv234567的博客 298

56、宇宙微波背景辐射(CMB)望远镜及光学系统解析

本文详细解析了宇宙微波背景辐射(CMB)望远镜及其光学系统,重点介绍了交叉德拉贡系统的结构特点、偏振测量误差及其控制、以及大型地面望远镜如ACT和SPT的设计与对比。同时,总结了不同光学系统和探测器阵列的优劣势,并展望了未来发展方向,旨在为CMB研究提供更高效的工具和技术支持。

f9g0h的博客 244

手写实现自定义线程池,并发编程之手撕线程池,徒手做个Java线程池,自定义ThreadPool

java、juc

zhangfuping123456789的博客 7147

谁在 SAP 系统里说了算:事务码 SCC4 与 SE06 的分工、优先级与实战管控

SAP系统通过SE06和SCC4两套机制控制变更权限:SE06作为系统级"总闸"管理跨Client对象修改,SCC4作为Client级"分闸"控制Client内配置变更。两者存在明确优先级,SE06的全局设置优先于SCC4。当SE06设为"不可修改"时,即使SCC4开放也无法更改跨Client对象。实际项目中需同时检查两处设置,并遵循"最小开放"原则进行变更管理。这种分层设计既满足日常维护需求,又能实现严格的变更管控。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 229

Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列

开个新坑-手搓简易线程池。本系列文章将从零开始,一步步手工编码实现一个简单但功能完备的线程池。我们将逐步介绍线程池的各个核心组件,并分析它们的作用和实现思路。通过这个过程,我们可以更好地掌握多线程编程的技巧,并培养编码能力和系统性思维。

qq_35716689的博客 25万+

RK3568平台开发系列讲解(项目篇)手写数字识别

📢 本篇章带大家基于飞桨(PaddlePaddle),完成一个简单的手写数字识别任务。

内核笔记 1183

mjlab MuJoCo 人形机器人强化学习入门教程(一)安装配置使用

mjlab是融合IsaacLab API与MuJoCo物理引擎的强化学习工具,提供轻量级GPU加速仿真方案。当前处于测试阶段,支持Linux系统(推荐)和有限macOS支持。核心优势包括:1)直接集成MuJoCo Warp实现裸机性能;2)保留IsaacLab成熟的RL抽象层;3)简化安装流程。与IsaacLab相比更专注于MuJoCo生态,适合刚体机器人RL研究。文档包含详细安装指南、平台兼容性说明、与IsaacLab的API差异对比及常见问题解答。项目正在积极开发中,欢迎社区贡献和反馈。

2506_90492529的博客 2002

Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现

在前面几篇文章中,我们已经实现了线程池的核心功能:任务队列、执行逻辑以及线程管理。本次我们将继续扩展补充线程池的功能,为线程池添加生命周期管理。通过引入生命周期,我们能够更加灵活地管理和控制线程的创建、运行和销毁过程。可以更好地处理资源分配、任务调度和系统稳定性等方面的问题。

qq_35716689的博客 1万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

初始JavaEE篇——多线程(6):线程池

线程池、Java标准可中的线程池、模拟实现线程池

我要学编程的博客 1807

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java多线程实战-从零手搓一个简易线程池(二)线程池实现与拒绝策略接口定义

在前面的文章中,我们讲解了任务堵塞队列的实现,这篇文章会基于任务堵塞队列实现一个简易的线程池,在后续的文章中,还会继续对本章编写的线程池进行功能扩展和优化。

qq_35716689的博客 24万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java多线程案例——线程池

Java多线程案例——线程池

如风暖阳的博客 1万+

Java【多线程】(5)线程池

哈喽大家好吖,今天来给大家继续进行多线程——线程池方面的学习,线程池在以后项目中也是关键的存在,废话不多说让我们开始吧。

2301_81073317的博客 3411

【Java学习笔记】多线程与线程池

需要的时候可以快速使用,不用重新收集。

qq_45192089的博客 1413

Java教程:Java多线程,线程池的入门学习与深入理解

多线程是Java中必不可少的一个环节,它通常以多个或几十个并行线路同时处理业务功能,从而大大提高了程序运行的效率,大多数情况下,我们的程序都是以单线程方式运行的,这个线程也被称为主线程,当程序中为主线程开辟出多个并行线程时,它的工作被分摊到各个线程中同时处理,这些同时运行的线程也被称为子线程、主线程的结束,并不会影响子线程的运行,各自为战,互不牵扯。

wfeil211的博客 1080

【多线程】Java如何实现多线程?如何保证线程安全?如何自定义线程池?

线程是操作系统能够进行运算调度的最小单位。它被包含在进程中,是进程中的实际运作单位。 进程是程序的基本执行实体。 - 并发:在同一时刻,有多个指令在单个CPU上**交替**执行。 - 并行:在同一时刻,有多个指令在单个CPU上**同时**进行。

ebb29bbe的博客 1869

Java进阶学习|Day4.Java多线程,线程池

多线程其实就是,老板请多个员工同时做事,一个进程就相当于一个项目组去做一个项目,多个线程组成了一个进程,就相当于这个项目组有多个员工同时做事.

weixin_60364343的博客 1558

Java多线程学习笔记(七)--线程池

什么是线程池 为了避免系统频繁地创建和销毁线程,我们可以让创建的线程进行复用,线程池是来管理线程的,线程池中总有那么几个活跃线程,当使用线程时可以从池子中随便拿一个空闲线程,当完成工作时,不用立即关闭线程,而是将线程还给线程池,方便下一个要使用线程的任务,有了线程池后,创建线程变成是从线程池中拿线程,销毁线程时变成是将线程还给线程池继续管理。 这种场景非常像在开发中连接数据库,有一个数据库连...

至尊宝 2万+
上一篇: JAVA多线程学习5:自己实现一个boolean锁
下一篇: java多线程设计模式大纲
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值