Coding面试题之手写线程池

news2024/11/24 19:53:49

原理图 

JDK线程池原理

 实现代码

1.线程类(PoolThread

这个类用于执行任务队列中的任务。

public class PoolThread extends Thread {
    private final Queue<Runnable> taskQueue;
    private boolean isStopped = false;

    public PoolThread(Queue<Runnable> queue) {
        taskQueue = queue;
    }

    public void run() {
        while (!isStopped()) {
            try {
                Runnable runnable;
                synchronized (taskQueue) {
                    while (taskQueue.isEmpty()) {
                        taskQueue.wait();
                    }
                    runnable = taskQueue.poll();
                }
                runnable.run();
            } catch (Exception e) {
                // 异常处理
            }
        }
    }

    public synchronized void stopThread() {
        isStopped = true;
        this.interrupt(); // 中断线程
    }

    public synchronized boolean isStopped() {
        return isStopped;
    }
}

2.线程池类(ExtendedThreadPool

这个类用于管理线程和任务的分配。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;

public class ExtendedThreadPool {
    private final Queue<Runnable> taskQueue;
    private final List<PoolThread> threads;
    private boolean isStopped;

    private int maxNumThreadSize;
    private int minNumThreadSize;
    private int keepAliveTime;
    private Timer maintainTimer;

    public ExtendedThreadPool(int minNumThreadSize, int maxNumThreadSize, int keepAliveTime) {
        this.minNumThreadSize = minNumThreadSize;
        this.maxNumThreadSize = maxNumThreadSize;
        this.keepAliveTime = keepAliveTime;
        this.taskQueue = new LinkedList<>();
        this.threads = new ArrayList<>();
        this.isStopped = false;
        this.maintainTimer = new Timer();

        for (int i = 0; i < this.minNumThreadSize; i++) {
            threads.add(new PoolThread(taskQueue));
        }

        for (PoolThread thread : threads) {
            thread.start();
        }

        maintainThreadPool();
    }

    public synchronized void execute(Runnable task) {
        if (this.isStopped) throw new IllegalStateException("ThreadPool is stopped");

        this.taskQueue.add(task);
        this.taskQueue.notify();

        if (threads.size() < maxNumThreadSize) {
            PoolThread newThread = new PoolThread(taskQueue);
            threads.add(newThread);
            newThread.start();
        }
    }

private void maintainThreadPool() {
    maintainTimer.schedule(new TimerTask() {
        @Override
        public void run() {
            synchronized (taskQueue) {
                // 如果任务多于线程,且线程数小于最大线程数,则增加线程
                if (!taskQueue.isEmpty()  && taskQueue.size()> threads.size()  &&  threads.size() < maxNumThreadSize) {
                    PoolThread newThread = new PoolThread(taskQueue);
                    threads.add(newThread);
                    newThread.start();
                }

                // 检查线程是否超过空闲时间,如果是,则移除线程
                Iterator<PoolThread> iterator = threads.iterator();
                while (iterator.hasNext()) {
                    PoolThread thread = iterator.next();
                    if (thread.isIdleFor(keepAliveTime)) {
                        iterator.remove();
                        thread.stopThread();
                    }
                }
            }
        }
    }, 0, keepAliveTime * 1000);
}


    public synchronized void stop() {
        this.isStopped = true;
        for (PoolThread thread : threads) {
            thread.stopThread();
        }
        maintainTimer.cancel();
    }
}

上面的代码如何保证线程复用?

  1. 任务到达时唤醒: 当一个新任务被添加到队列中并且队列之前是空的,execute 方法会调用 taskQueue.notify();,这会唤醒一个正在等待的线程。被唤醒的线程随后会从队列中取出任务并执行。

  2. 线程不立即终止: 线程在执行完一个任务后不会立即终止。相反,它会再次检查队列是否有新的任务。如果有,线程会继续执行新的任务。

相关文章

【精选】线程池的核心参数和运行机制_线程池的核心参数以及工作机制-CSDN博客

线程池内运行的线程抛异常,线程池会怎么办_线程池线程异常后会结束线程吗-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1194694.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python---练习:求幸运数字6

案例&#xff1a; 幸运数字6&#xff08;只要是6的倍数&#xff09;&#xff1a;输入任意数字&#xff0c;如数字8&#xff0c;生成nums列表&#xff0c;元素值为1~8&#xff0c;从中选取幸运数字移动到新列表lucky&#xff0c;打印nums与lucky。 思考&#xff1a; 要求是6的…

说说 React中的setState执行机制

一、是什么 一个组件的显示形态可以由数据状态和外部参数所决定&#xff0c;而数据状态就是state 当需要修改里面的值的状态需要通过调用setState来改变&#xff0c;从而达到更新组件内部数据的作用 如下例子&#xff1a; import React, { Component } from react export d…

ARM 基础学习记录 / ARM 裸机编程

汇编程序调用 C 程序详情 在 C 程序和 ARM 汇编程序之间相互调用时必须遵守 ATPCS 规则&#xff0c;其是基于 ARM 指令集和 THUMB 指令集过程调用的规范&#xff0c;规定了调用函数如何传递参数&#xff0c;被调用函数如何获取参数&#xff0c;以何种方式传递函数返回值。 寄存…

Linux内核有什么之内存管理子系统有什么第六回 —— 小内存分配(4)

接前一篇文章&#xff1a;Linux内核有什么之内存管理子系统有什么第五回 —— 小内存分配&#xff08;3&#xff09; 本文内容参考&#xff1a; linux进程虚拟地址空间 《趣谈Linux操作系统 核心原理篇&#xff1a;第四部分 内存管理—— 刘超》 特此致谢&#xff01; 二、小…

SpringData、SparkStreaming和Flink集成Elasticsearch

本文代码链接&#xff1a;https://download.csdn.net/download/shangjg03/88522188 1 Spring Data框架集成 1.1 Spring Data框架介绍 Spring Data是一个用于简化数据库、非关系型数据库、索引库访问&#xff0c;并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快…

vue项目pdf文件的预览

1.下载 您可以在以下网址下载pdfjsLib&#xff1a;https://github.com/mozilla/pdf.js pdfjsLib是一个开源项目&#xff0c;您可以在GitHub上找到其源代码和相关资源。 2.放置文件位置 3.进入 在index.html引入 <script src"<% BASE_URL %>static/pdfjs-dist/b…

赛宁网安入选国家工业信息安全漏洞库(CICSVD)2023年度技术组成员单

近日&#xff0c;由国家工业信息安全发展研究中心、工业信息安全产业发展联盟主办的“2023工业信息安全大会”在北京成功举行。 会上&#xff0c;国家工业信息安全发展研究中心对为国家工业信息安全漏洞库&#xff08;CICSVD&#xff09;提供技术支持的单位授牌表彰。北京赛宁…

WPF ToggleButton 主题切换动画按钮

WPF ToggleButton 主题切换动画按钮 仿造最近看到的html中的一个效果&#xff0c;大致思路是文章这样&#xff0c;感觉还可以再雕琢一下。 代码如下 XAML: <UserControl x:Class"WPFSwitch.AnimationSwitch"xmlns"http://schemas.microsoft.com/winfx/200…

8255 boot介绍及bring up经验分享

这篇文章会简单的介绍8255的启动流程&#xff0c;然后着重介绍8255在实际项目中新硬件上的bring up工作&#xff0c;可以给大家做些参考。 8255 boot介绍 下面这些信息来自文档&#xff1a;《QAM8255P IVI Boot and CoreBSP Architecture Technical Overview》 80-42847-11 R…

Django debug page XSS漏洞复现_(CVE-2017-12794)

Django debug page XSS漏洞复现_(CVE-2017-12794) 复现过程 首先进入靶场环境 按照他写的&#xff0c;需要给这个变量赋值 创建一个用户&#xff0c;用弹窗做用户名 http://10.4.7.137:8000/create_user/?username<script>alert(1)</script>返回&#xff0c;然…

Unity中Shader的间接光的产生Meta Pass

文章目录 前言Unity中Shader的间接光的产生Meta Pass&#xff0c;这也是属于全局光照 GI 的内容。主要实现像现实生活中&#xff0c;光线照到有颜色的物体后&#xff0c;该物体有反射出该颜色的光的效果。 一、我们先使用Unity自带的Shader看看间接光效果1、先按照如下设置搭建…

C++ | 继承和多态

目录 继承 继承的概念及用法 继承的作用域 向上转型和向下转型 继承过程中的默认生成函数 菱形继承及其解决方案 - 虚继承 虚继承的原理 - 虚基类表 继承和组合 多态 虚函数 多态的定义及使用 纯虚函数与抽象类 多态的原理 小点补充 虚表的位置 父类指针new一个…

聊聊测试左移到需求阶段

这是鼎叔的第七十九篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 欢迎关注本公众号《敏捷测试转型》&#xff0c;星标收藏&#xff0c;大量原创思考文章陆续推出。本人新书《无测试组织-测试团队的敏捷转型》​​​​​​​已出版&#xff08;机械工业出版…

单链表的基本操作代码

#include<stdio.h> #include<stdlib.h> typedef int Status;//函数类型&#xff08;当return值为函数结果状态时用&#xff09;需要自定义&#xff01; typedef int ElemType;//相当于给 int起个别名 typedef struct LinkList{ ElemType data; struct L…

JMeter实现持续压测websocket

1、安装插件&#xff1a;JMeter WebSocket Samplers pjtr / JMeter WebSocket Samplers / Downloads — Bitbuckethttps://bitbucket.org/pjtr/jmeter-websocket-samplers/downloads/ 将下载的Jar包放在安装jmeter的/lib/ext路径下&#xff0c;重启生效 查看测试计划--》配置…

python爬虫怎么翻页

爬虫程序的代码实现如下&#xff1a; #include <iostream> #include <string> #include <curl/curl.h>int main() {CURL *curl;CURLcode res;std::string readBuffer;curl_global_init(CURL_GLOBAL_DEFAULT);curl curl_easy_init();if(curl) {curl_easy_se…

ChatGPT、GPT-4 Turbo接口调用(stream模式)

接口地址 https://chat.xutongbao.top/api/light/chat/createChatCompletion 请求方式 post 请求参数 model可选值&#xff1a; “gpt-3.5-turbo-1106”、 “gpt-3.5-turbo-16k” 、 “gpt-4”、“gpt-4-1106-preview”。 默认值为&#xff1a; “gpt-3.5-turbo-1106” to…

LeetCode 17. 电话号码的字母组合 中等

题目 - 点击直达 1. 17. 电话号码的字母组合 中等1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 3. 知识与收获 1. 17. 电话号码的字母组合 中等 1. 题目详情 1. 原题链接 LeetCode 17. 电话号码的字母组合 中等 2. 题目要…

后端架构选择:构建安全强大的知识付费小程序平台

构建知识付费小程序平台需要考虑后端架构&#xff0c;确保系统安全性、性能和可扩展性。以下是一些常见的后端技术和最佳实践&#xff0c;能帮助您构建强大且安全的知识付费小程序平台。 1. 服务器端语言和框架选择 选择流行、成熟的后端语言和框架&#xff0c;如Node.js、P…

基于php js+mysql+laravel技术架构的手术麻醉管理系统源码 手麻系统源码

PHP手术麻醉管理系统源码 手麻系统源码 手术麻醉管理系统定义&#xff1a; 手术麻醉系统主要是由麻醉信息管理和监护设备数据采集系统两个部分组成&#xff0c;主要是将麻醉信息和从监护仪器上采集到的数据以及手术信息进行统计。 手术麻醉系统是指专用于住院患者手术与麻醉…