JAVA-线程池的基本原理

Java 线程池(Thread Pools)详解 线程池是一种重用线程的机制,用于提高线程的利用率和管理线程的生命周期,常用于多线程编程和异步编程。Java提供了多种线程池实现,其中最常用的是ThreadPoolExecutor类和Executors类提供的静态工厂方法。线程池由一个线程队列和一个任务队列组成,线程队列中保存着空闲线程,任务队列中保存着等待执行的任务。线程池启动后,线程池中的线程从任务队列中获取任务并执行,执行完毕后返回线程队列中等待下一次任务的到来。如果任务队列为空,线程池中的线程将等待新的任务到来或被关闭。 阅读详情

JAVA-快速了解线程池的基本原理

前言

       说起线程池大家肯定不会陌生,在面试中属于必问的问题之一,特别是对于“高并发”有较高要求的企业,基本是必问点。网上关于线程池的文章和视频很多,本篇文章旨在帮助大家快速了解和掌握线程池的基本原理,对于高级应用不过多涉及。


 

目录

  1. 并发队列
  2. 线程池简介
  3. 为什么需要线程池
  4. 线程池原理
  5. 线程池的分类


     

一、并发队列

1. 并发队列概念

       并发队列是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。
 

2. 并发队列分类

       并发队列分为阻塞队列和非阻塞队列,下面举例示意:
       现有一个长度为10的队列,有11个元素需要放进去
Alt
                                              示意图

两种队列区别

  1. 入队时
    非阻塞队列:当向队列中放入10个元素,此时队列已满,再放入第11个元素数据就会丢失。

    阻塞队列:当队列已满了的时候,此时会进行等待,什么时候队列中有出队的元素,那么第11个再放进去。

  2. 出队时
    非阻塞队列:如果队列中没有元素了,此时进行出队操作,往外取元素,得到的就是null。

    阻塞队列:当队列中没有元素时,如果此时进行出队操作会等待,什么时候放进去,什么时候再取出来。

       特别地,线程池就是基于阻塞队列实现的。


 

二、线程池简介

 

       线程池是一种多线程处理形式,处理过程中将任务添加到队列,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务。执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。

 

       简单来说,线程池就是线程的集合。


 

三、为什么需要线程池

 

线程的正常生命周期如下图所示:
在这里插入图片描述       为了便于分析,假设各阶段所花时间如上所示(当然线程各阶段实际所花时间极短,为毫秒级)。如果我们能省略其他阶段,每次线程直接运行任务,这样就可以单个线程处理任务就可以节省5秒。要实现这样的设想,我们可以使用线程池来处理,因为线程池中的线程是事先创建好的大量空闲线程,当队列中的任务进入线程池中,线程可以直接执行任务,执行完成后释放资源,继续处理下一任务。
       举例来看:现有100个任务需要处理,一次最多创建10个线程。如果采用普通方式,一次创建10个线程处理10个任务,总共需60秒,而采用线程池的方式,一次执行10个任务,总共需要10秒。
       综上所述:我们可以很明显的看出线程池在处理任务量极大的高并发系统中,具有很大的优势。

 

四、线程池的原理

 

1. ThreadPoolExecutor核心类

       线程池的最上层接口是Executor,这个接口定义了一个核心方法execute(Runnablecommand),这个方法是用来传入任务的,最后被ThreadPoolExecutor类实现。而且ThreadPoolExecutor是线程池的核心类,此类的构造方法如下:

 

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
 
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnitunit,BlockingQueue<Runnable>workQueue,RejectedExecutionHandler handler);
 
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

 

各个参数表示意义:

参数名参数含义
corePoolSize核心线程池大小,也即核心线程的数量
maximumPoolSize最大线程池大小,也即线程的最大数量
keepAliveTime空闲时间,是除核心线程之外的新创建线程的最大存活时间
TimeUnit时间单位
workQueue阻塞队列,用来存储等待的任务
threadFactory线程工厂,用来创建新线程
handler拒绝处理策略,当提交给线程池的任务量超过最大线程池大小+队列长度,就会采取拒绝处理策略

特别地说明:
workQueue一般有以下三种阻塞队列:
SynchronousQueue:直接提交,默认使用队列
ArrayBlockingQueue:有界队列
LinkedBlockingQueue:无界队列

threadFactory是当队列已满,但线程总数量<最大线程池大小时,线程池中用来创建新线程的线程工厂。一般有下列三种类型:
ArrayBlockingQueue:有界线程安全的阻塞队列。
LinkedBlockingQueue:并发安全的阻塞队列。
SynchronousQueue:同步队列。

handler触发时,有以下四种拒绝处理策略:
hreadPoolExecutor.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

 

2.线程池原理图

在这里插入图片描述

3. 线程池实例

       接下来就通过一个简单的实例并结合原理图来了解线程池的基本原理:

 

public class test02 {
    public static void main(String[] args) {
        ThreadPoolExecutor pool =
        new ThreadPoolExecutor(1,2,3, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3));
        //利用线程池中的线程开始执行任务
        //执行第一个任务
        pool.execute(new TestThread());
        
        //队列有三个任务等待
        pool.execute(new TestThread());
        pool.execute(new TestThread());
        pool.execute(new TestThread());
        
        //执行第五个任务
        pool.execute(new TestThread());
        //执行第六个任务,拒绝任务报错
        //pool.execute(new TestThread());
        //当前线程池中有2个线程:1个核心线程 + 1个新创建的线程 = 最大线程数

        //关闭线程池
        pool.shutdown();
    }
}

class TestThread implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

 

       首先创建一个最简单类型的线程池,构造方法只有五个参数,每个参数意义如下:
1:核心线程数
2:最大线程数
3:空闲时间。新创建的线程执行任务后等待新任务的空闲时间
TimeUnit.SECONDS:时间单位,秒
new LinkedBlockingDeque:阻塞队列,长度为3




 

不执行第6条任务时的执行结果如下:

在这里插入图片描述

 

执行第6条任务时执行结果如下:
在这里插入图片描述
 

分析代码执行过程:

在这里插入图片描述
       现有一线程池,里面只有一个核心线程thread1,第一个任务进入线程池中,由thread1执行,而2-4号线程处在队列中等待执行,当5号任务提交时,根据原理图,此时满足队列已满,且核+新<=最大,所以创建新线程thread2,由thread1和thread2分摊执行任务,由运行结果也可以看出,确实是分摊任务。

       当加上第6条的任务时,根据原理图,此时队列已满,且核+新>最大,没有多余的线程执行任务,队列也无法装入,就会报错,拒绝任务。


 

五、线程池的分类

 

线程池可分为以下四类:

 

1. 可缓存:newCachedThreadPool

  • 作用:创建一个根据需要创建新线程池的线程池。当旧线程释放资源后就可以使用旧线程。

  • 特点:线程数灵活最大值为INTER.MAX_VALUE,底层采用一个近似无边界队列
     

2. 定长:newFixedThreadPool

  • 作用:创建一个可重用固定线程数的线程池,以共享的无界队列来运行这些线程。

  • 特点:线程处于一定量,可以很好的控制并发量
     

 

3. 定时:newScheduleThreadPool

  • 作用:创建一个可延迟或延期运行的线程池。

  • 特点:线程池中具有指定数量的线程,可定时或延迟执行,适用于周期性执行任务的场景。
     

4. 单例:newSingleThreadExecutor

  • 作用:创建一个只有一个线程的线程池。且线程的存货时间是无限的,当该线程正繁忙时,对于新任务会进入无界的阻塞队列中。
  • 特点:适用于一个一个任务执行的场景。
Java线程池详解:高效并发编程的核心利器 线程池就像一个"线程工厂",它预先创建一定数量的工作线程并放在"池子"里待命。当有任务需要执行时,不需要重新创建线程,而是直接从池子里取一个空闲线程来干活。任务完成后,线程不会被销毁,而是重新回到池子里等待下一个任务。这就好比一个餐厅,与其每来一个客人就临时招聘一个服务员,不如提前雇好几个服务员待命,这样既节省了招聘成本,又能保证服务质量。线程池是Java并发编程的核心工具,掌握其原理和配置对于构建高性能应用至关重要。 阅读详情

相关推荐

HLM(多层线性模型)在stata中语句

在阅读CEPS中发现有些研究采用的是HLM模型,HLM简单来说用一个方程跑两个回归。举例,对学习成绩影响因素,不同层有不同的影响,如在个体层面上个体特征会对成绩产生影响,在学校层面学校排名等因素会对成绩产生影响,两种因素不在一个层面,每层造成的差异都不相同。 在找相关语句时候发现操作这个语句的软件大多是SPSS和HLM,对于stata操作者并不友好。因此,在有限资料中总结了HLM在stata中的语句,后面会附上学习视频和链接。 先放语句,后面对方程式一个大致解析。由于针对HLM有一本书的介绍,可能一篇文章无

weixin_44652251的博客 1万+

全面解读Java线程池的工作原理

一、为什么引入线程池技术? 二、Executor框架 2.1 Runnable、Callable与Future接口 2.2 Executor接口 三、Java中线程池的工作原理 3.1 ThreadPoolExecutor中核心的变量及常量 3.2 线程池的任务调度逻辑 3.3 线程池的关闭流程 四、线程池的使用 4.1 FixedThreadPool 4.2 SingleThreadExecutor 4.3 CachedThreadPool

BUPTZhanggg的博客 3391

Oracle19c SYSAUX表空间爆满?手把手教你清理SM/ADVISOR和AUDSYS占用(附完整SQL)

本文详细解析了Oracle19c中SYSAUX表空间爆满的常见原因及解决方案,重点针对SM/ADVISOR和AUDSYS组件的空间占用问题提供了完整的SQL清理脚本。通过诊断查询、空间清理和预防性维护策略,帮助DBA有效管理SYSAUX表空间,确保数据库稳定运行。

weixin_28338005的博客 238

详述Java线程池实现原理

线程池是什么 线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,处理完之后线程并不会被销毁,而是仍然在线程池中等待下一个任务。 使用线程池有什么好处 降低资源消耗:通过重复利用现有的线程来执行任务,避免多次创建和销毁线程 提高响应速度:因为省去了创建线程这个步骤,所以在拿到任务时,可以立刻开始执行 提供附加功能:线程池的可拓展性使得我们可以自己加入新的功能,比如说定时、延时来执行某些线程 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统

养歌的博客 3070

单细胞测序流程(八)单细胞的marker基因转化和​GO富集分析

系列文章目录 单细胞测序流程(一)简介与数据下载 单细胞测序流程(二)数据整理 单细胞测序流程(三)质控和数据过滤——Seurat包分析,小提琴图和基因离差散点图 单细胞测序流程(四)主成分分析——PCA 单细胞测序流程(五)t-sne聚类分析和寻找marker基因 单细胞测序流程(六)单细胞的细胞类型的注释 单细胞测序流程(七)单细胞的细胞类型轨迹分析———————————————— 本期主讲内容——单细胞的maeker基因转化和​富集分析 marker基因转化是为了将基因的id和基.

qq_45478665的博客 1万+

深入解析Transformer三大注意力机制:自注意力、交叉注意力与因果自注意力

注意力机制是深度学习中的核心概念,它模拟了人类在处理信息时选择性聚焦的能力。其基本原理是通过计算查询与键的相似度,动态地为值分配权重,从而提取关键信息。这一机制解决了传统序列模型(如RNN)难以并行化和捕获长距离依赖的痛点,技术价值在于显著提升了模型的计算效率和表征能力。在自然语言处理、计算机视觉等应用场景中,注意力机制已成为构建强大模型的基石。本文聚焦于Transformer架构中的三种核心注意力变体:自注意力用于建立序列内部的全局关联,交叉注意力连接编码器与解码器的信息,而因果自注意力则确保自回归生成的

weixin_29094775的博客 413

Java 线程池的工作原理

Java 线程池主要是用于管理线程组及其运行状态,以便 Java 虚拟机更好地利用 CPU 资源。 Java 线程池的工作原理为:JVM 先根据用户的参数创建一定数量的可运行的线程任务,并将其放入队列当中,在线程创建好后启动这些任务,如果正在运行的线程数量超过了线程池的最大线程数量(线程池的数量是用户自己设置的),那么超出的数量的线程排队等待,在有任务执行完毕后,线程池调度器会发现有可用的线程,进而再次从队列中取出任务并执行。线程池的主要作用就是线程复用,线程资源管理,控制操作系统的最大并发数,以保证系统的

古城的博客 7537

Windows+VSCode+Cline+MCP全流程配置指南

本文提供了一份详细的Windows+VSCode+Cline+MCP全流程配置指南,旨在帮助开发者打造高效的AI辅助编码工作站。文章从环境准备讲起,逐步指导安装VSCode、配置Cline插件、搭建Node.js环境,并重点详解如何通过MCP为Cline集成文件系统和GitHub等工具服务器,实现用自然语言操控开发环境,从而显著提升日常编码与文件管理效率。

weixin_28840143的博客 553

JAVA-快速了解线程池的基本原理

前言:说起线程池大家肯定不会陌生,在面试中属于必问的问题之一,特别是对于“高并发”有较高要求的企业,基本是必问点。网上关于线程池的文章和视频很多,本篇文章旨在帮助大家快速...

weixin_45737309的博客 141

幻尔串口总线舵机控制Python SDK

幻尔串口总线舵机控制Python SDK,可以直接在PC端,不需要借助单片机对舵机进行控制。

daishabby2486的博客 4092

ultralytics.data.utils——utils.py子模块代码详读

ultralytics.data.utils——utils.py子模块代码详读

Together_CZ的博客 1721

JAVA线程池的基本原理(一)

前言        说起线程池大家肯定不会陌生,在面试中属于必问...

ls490447406的博客 164

YOLO项目部署:从Python脚本到Docker容器的企业级交付全流程

YOLO模型企业级Docker部署方案 核心挑战 环境一致性:解决"本地能跑,服务器崩掉"问题 可扩展性:支持单实例到多实例扩展 稳定性:确保99.9%可用性 部署流程 项目改造:模块化代码,分离配置 Docker镜像:支持CPU/GPU环境 API服务:封装推理逻辑 监控告警:实现自动化运维 技术方案 需求 解决方案 环境一致性 Docker镜像+依赖冻结 可扩展性 K8s+负载均衡 稳定性 健康检查+自动重启 项目结构 模块化代码组织 外部化配置管理 精确依赖版本控制 摘要重点:通过

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1230

Java线程池基本原理

Executors类似于Collections作用域集合领域一样,它是线程池的工具类,可以通过静态方法构造出不同特性的线程池让我们快速使用。常见的Executors创建线程池有几种: 1.2 ExecutorService接口 ExecutorService接口继承自Executor接口,Executor接口至定义了一个execute(Runnable r)抽象方法,ExecutorService是对Executor的补充,它定义了线程池的一系列同样方法: 1.3 自定义线程池ThreadPoolExecu

Minor的Java技术博客 202

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java线程池的基本原理

Java线程池的实现原理分析 最近读了下线程池的源码(jdk1.7版本),学习了线程池的实现原理,感觉很有帮助,本想自己写一篇文章介绍下源码,但是看到这个系列的源码分析的真心好,所以就转载了.......以下是原文内容: 线程池是可以控制线程创建、释放,并通过某种策略尝试复用线程去执行任务的一种管

刘阳的博客 253

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

JAVA线程池的基本原理是什么?

Java线程池的基本原理是:线程池是一个用于管理线程的组件,它可以创建一个线程队列,并将请求的任务放入队列中,然后在线程空闲时将任务取出并执行。这样做的好处是可以避免频繁的线程创建和销毁对系统造成的性能开销,并且可以很方便地控制线程数量,从而保证系统在可控制的范围内达到最佳性能。 ...

weixin_35750483的博客 554

Java线程池基本原理(源码剖析)

基本原理源码 要理解原理,仍然要从源码看起。Java8的线程池【ThreadPoolExecutor】构造方法如下, public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, .

xiaohong_2021的博客 276
上一篇: BigDecimal 的四舍五入函数详解
下一篇: Spring 事务 -- @Transactional
Java_2017_csdn
博客等级 码龄10年 329粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值