Java线程详解及多线程线程池使用与原理

Java多线程并发编程系列-00 线程池原理与自定义实现线程池 本文探讨了Java多线程并发编程中的线程池原理与实现。多线程的核心目的是充分利用CPU资源并发执行任务,但线程并非越多越好,需权衡创建/销毁开销、内存消耗及上下文切换成本。线程池通过固定数量的工作线程和任务队列(BlockingQueue)实现高效任务调度:任务提交到队列,空闲线程获取任务执行。针对计算型与IO型任务,线程数需动态调整(如CPU核数的1-2倍或更高)。文中还实现了一个简易线程池(FixedSizeThreadPool),包含任务队列、工作线程集合及关闭逻辑,并对比了阻塞(put/ta 阅读详情

一、Java线程

本文主要介绍线程的基本概念与创建方式和多线程线程池的详解以及使用

1.1 什么是线程

要了解线程首先我们要知道什么是进程,进程与线程之间的关系

  • 进程
    进程是操作系统进行资源分配和调度的一个独立单位, 系统中每一个运行的程序都是一个进程,每个进程都有自己独立的内存空间。
  • 线程
    线程是操作系统进行运算调度的最小单位, 被包含在进程中,每个进程可以同时拥有多个线程。

1.2 线程创建

线程的创建有三种方式: 继承Thread类、实现Runnable接口、实现Callable接口

  • 继承Thread,重写run方法
public class TestThread extends Thread{
    private int count=0;
    @Override
    public void run() {
        //需要线程执行的逻辑
        for (int i = 0; i < 10; i++) {
            System.out.println(count++);
        }
    }
    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        //启动线程
        testThread.start();
    }
}
  • 实现Runnable接口,重写run方法
public class TestThread1 implements Runnable{
    private int count=0;
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(count++);
        }
    }
    public static void main(String[] args) {
        TestThread1 testThread1 = new TestThread1();
        //把实现了runable接口的实现类对象作为参数,放到thread的构造方法
        Thread thread = new Thread(testThread1);
        //启动线程
        thread.start();
    }
}
  • 实现Callable接口,重写call方法
//Callable接口与Runnable接口不同的是Callable接口的call方法是具有返回值的,
//如果有需要线程具有返回数据的情况使用callable
public class TestThread2 implements Callable {
    private int count = 0;
    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(count++);
        }
        return count;
    }
public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestThread2 testThread2 = new TestThread2();
        FutureTask task = new FutureTask(testThread2);
        Thread thread = new Thread(task);
        thread.start();
        Object o = task.get();
        System.out.println("count值为:"+o);

    }
}

1.3 线程状态

线程具有五种状态分别是新建、就绪、运行、阻塞、死亡。

  • 新建:当我们new Thread()对象时,该线程对象就处于新建状态
  • 就绪:当我们调用start()方法时,该线程进入就绪状态,此时的线程进入到试图获取cpu资源的状态。
  • 运行:当就绪线程获取到cpu执行权时,线程进入到运行状态。
  • 死亡:当线程正常执行结束或者调用stop方法后,线程进入死亡状态。
  • 阻塞:当线程进入睡眠,等待,或因获取锁被阻塞时进入到阻塞状态。
    当调用Thread类的sleep方法时,线程进入到睡眠状态,在睡眠指定时间后进入到就绪状态
    当调用Thread类的yield等方法时,线程会让步其它线程执行,线程进入到等待状态

二、多线程线程池

  • 为什么要使用线程池?
    在需要使用大量线程的业务场景,我们需要频繁的创建线程,当线程执行完需要进行销毁线程,每当有新任务我们都需要重新创建线程,这样频繁的创建销毁线程会大大占用系统开销。
  • 使用线程池有哪些优势?
    降低资源消耗,通过重复利用已创建线程降低线程创建和销毁造成的消耗。
    提高响应速度,当任务到达时,任务可以不需要等待线程创建就能立即执行。
    提高线程可管理性,线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

2.1 线程池工作原理

在这里插入图片描述

2.2 ThreadPoolExecutor详解

  • 如何使用线程池?
    要使用线程池我们先了解ThreadPoolExecutor类
    该类具有四个构造方法,另外三个都会调用其中一个,让我们看看这个构造方法包含哪些参数
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 

1、corePoolSize: 核心线程数,该线程池可以创建的执行任务的核心线程数量
2、maximumPoolSize:最大线程数,指当corePoolSize与workQueue存储满时,线程池会创建非核心线程执行任务,maximumPoolSize为线程池可存活最大线程数。
3、keepAliveTime:最大等待时间,指非核心线程数的等待时间, 核心线程被创建后会永久存在等待任务到来,而非核心线程执行完任务会被销毁, 当空闲时间超过keepAliveTime,则会销毁非核心线程
4、unit:keepAliveTime的时间单位
//TimeUnit.DAYS; 天
//TimeUnit.HOURS; 小时
//TimeUnit.MINUTES; 分钟
//TimeUnit.SECONDS; 秒
//TimeUnit.MILLISECONDS; 毫秒
//TimeUnit.MICROSECONDS; 微妙
//TimeUnit.NANOSECONDS; 纳秒
5、workQueue:等待队列,当线程池内线程数达到corePoolSize,则会将任务放于等待队列
常见的等待队列有以下三种类型
1)SynchronousQueue 直接提交策略
2)LinkedBlockingQueue 无界队列
3)ArrayBlockingQueue:、基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序
该队列当核心线程数达到最大值,新提交任务会存入队列,队列存储满会新建非核心线程,当总线程数达到maximumPoolSize,会使用拒绝策略来处理新提交任务。

  1. SynchronousQueue 直接提交策略

  2. LinkedBlockingQueue 无界队列
    该等待队列为无界队列,也就是会无限制添加,永远不会创建非核心线程,新加入任务永远会等待核心线程执行。

  3. ArrayBlockingQueue 有界队列
    该队列当核心线程数达到最大值,新提交任务会存入队列,队列存储满会新建非核心线程,当总线程数达到maximumPoolSize,会使用拒绝策略来处理新提交任务。

  4. PriorityBlockingQueue 具有优先级的无界队列

6、threadFactory :自定义线程工厂
7、handler :拒绝策略,线程池中线程数量超过最大值maximumPoolSize时调用的拒绝策略,常见有以下几种
1)AbortPolicy:中止策略。默认的拒绝策略,直接抛出 RejectedExecutionException
2)DiscardPolicy:直接抛弃请求过来的任务
3)DiscardOldestPolicy:抛弃队列中最先达到任务,然后将本次任务添加到队列
4)CallerRunsPolicy:由调用者线程执行该任务。即占用向线程池发送任务的线程,占用主线程,可以缓解线程池内部压力。

  • Executors 提供几个常见创建线程池方法
    1)newFixedThreadPool:固定线程数的线程池。核心线程数等于最大线程数,工作队列使用无界的LinkedBlockingQueue。适用于为了满足资源管理的需求,而需要限制当前线程数量的场景,适用于负载比较重的服务器。
    2)newSingleThreadExecutor:只有一个线程的线程池,即单线程线程池。适用于需要保证顺序的执行各个任务的场景。
    3)newFixedThreadPool:固定线程线程池,corePoolSize = maximumPoolSize,阻塞队列选取LinkedBlockingQueue,适用于限制当前线程数量的场景。
    4)newCachedThreadPool:该线程池核心线程数为0,最大线程数为 Integer.MAX_VALUE,线程存活时间为60s,该线程池可以无限扩张且会短时间内销毁空闲线程,适用于负载较轻服务器。
【Java多线程】线程池的工作原理详解(上) 为什么使用线程池 线程池为线程生命周期开销问题和资源不足问题提供了解决方案,因为线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配、调优和监控; 多线程技术可以解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力; 什么时候使用线程池 需要大量的线程来完成任务,且完成任务的时间比较短,如WEB服 阅读详情

相关推荐

【Java 多线程 2】java线程池原理

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

学Java,找哪吒 6561

Java线程池详细介绍——原理及详细使用

原文链接:https://www.toutiao.com/i6846340200134607374/ 关于线程和线程池的学习,我们可以从以下几个方面入手: 第一,什么是线程,线程和进程的区别是什么 第二,线程中的生命周期 第三,单线程和多线程 第四,线程安全 第五,为什么使用线程池 第六,线程池原理 第七,线程池的使用 第一,什么是线程,线程和进程的区别是什么? 线程,程序执行流的最小执行单位,是行程中的实际运作单位,经常容易和进程这个概念混淆。那么,线程和进程究竟有什么区别呢?首先,进

静远小和尚的博客 456

COMSOL模拟CO2驱替CH4:多物理场耦合建模与工程应用详解

在非常规天然气开发与碳封存工程中,多孔介质内的渗流、吸附与岩石变形相互耦合,使得CO2驱替CH4的产能预测和CO2封存评估无法仅靠经验公式完成。以达西定律描述裂隙流动、以扩展Langmuir方程刻画竞争吸附、用应力-吸附-渗透率关系关联煤岩变形,是多物理场耦合数值模拟的核心路径。COMSOL Multiphysics凭借内置渗流、固体力学与组分传递接口,能够将这些机制整合为可参数化扫描的仿真模型,为注气压力、井距、渗透率演化等方案设计提供量化依据。围绕CO2驱替CH4模拟的建模流程、参数取法与结果判读,可形

weixin_29574585的博客 160

【java】java多线程及线程池详解

java多线程及线程池面试题

酷酷的馫博客 1万+

本地如何安装midscene.js运行环境

手把手教你本地安装midscene.js运行环境

实践助梦想成长 2607

微信4.1.5.16升级后,你的自动化脚本失灵了?手把手教你用C#让UI树“复活”

微信4.1.5.16版本更新导致自动化脚本失效?本文深入解析微信UI树隐藏的原因,并提供C#实战解决方案,通过UIAutomation技术恢复UI树结构,帮助开发者重新实现自动化操作。涵盖技术原理、代码实现及优化策略,适合RPA开发者和自动化脚本编写者参考。

weixin_30879169的博客 519

java编程详解 pdf_Java高并发编程详解:多线程与架构设计 高清pdf扫描版[154MB]

《Java高并发编程详解》主要包含四个部分:部分主要阐述Thread的基础知识,详细介绍线程的API使用、线程安全、线程间数据通信,以及如何保护共享资源等内容,它是深入学习多线程内容的基础。第二部分引入了ClassLoader,这是因为ClassLoader与线程不无关系,我们可以通过synchronized关键字,或者Lock等显式锁的方式在代码的编写阶段对共享资源进行数据一致性保护,那么一个C...

weixin_42138376的博客 1083

《YOLOv12魔术师专栏》专栏介绍 & 专栏目录

《YOLOv12魔术师专栏》专栏介绍 & 专栏目录

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 5058

java 调用gpu_使用GPU加速Java、C++程序需要怎么操作?

gpu跑的是对应的gpu指令,并不是什么语言,cpu也一样。所有语言一样是要被编译成对应平台的机器指令。或者用解析器执行时转换成机器指令。python做深度学习,要做gpu加速,底层还是要通过编译器转换成gpu指令。所用的工具一般是CUDA,Opencl,DirectCompute.使用CUDA就是把C/C++代码编译成GPU的指令。再配合其他API调用代码,只能用在Nvidia的GPU。Open...

weixin_42523720的博客 6563

【异常】解决 Cursor 报错 Unexpected seqno: 2 != 1. Please try again, or contact support if the issue 的排坑指南

在使用 Cursor 辅助编程时,你是否遇到过 AI 突然中断输出,并在右下角弹出一个红色的 Network Error 弹窗?今天我们就来彻底解析并解决这个网络断连问题。

奶爸的编程之路,也就一周冷个三天 2470

ue 打包linux程序 在windows系统 2026

ue 打包linux程序 在windows系统 2026

jacke121的专栏 370

java 调用gpu_GPU使用设置

keras参考资料:https://keras.io/zh/getting-started/faq/#sample-batch-epochhttps://keras-cn.readthedocs.io/en/latest/参考资料:https://www.jianshu.com/p/5d47f152ff62https://blog.youkuaiyun.com/A632189007/article/detai...

weixin_29229989的博客 4054

科技与伦理的平衡点:人类计算的伦理

科技与伦理的平衡点:人类计算的伦理 关键词 科技与伦理 人类计算 隐私问题 道德决策自动化 公平性与偏见 法律与社会责任 摘要 本

AI天才研究院 1162

【Java 多线程】线程池 —— 详解线程池原理和使用

Java线程池是运用最多的并发框架,学号多线程以及合理的使用多线程可以带来很大的好处,今天就来一起学习线程池相关的知识吧! 线程池一、线程池的实现原理二、使用线程池1. 使用线程池的好处2.线程池的创建3. 向线程池提交任务4. 关闭线程池 一、线程池的实现原理 当向线程池提交一个任务后,线程池会怎么做呢? 首先线程池会在核心线程corePoolSize中找是否都在执行任务,如果不是,就创建...

Moo_Lavender的博客 604

以太网GMAC-RK3568

第 2 章和第 3 章中针对 RMII/RGMII 接口芯片和 USB 以太网两种类型芯片在 SDK 上的配置做详细的描述,第 4 章介绍以太网在 Android 上的相关调用接口。第 5 章提供常见问题的排查建议由于在 RK 系列的 SoC 中内置了以太网 MAC 控制器,所以只需要搭配一颗以太网 PHY 芯片,即可实现以太网卡功能按照规范,即使是不同厂家的 PHY,仍然有一部分寄存器的定义是通用的,只要配置了这些通用的寄存器,基本上 PHY 就可以正常工作代码位置在。

qq_24093081的博客 1942

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

java多线程(5):线程池原理及使用详解

前言 线程的创建和销毁太耗资源了,甚至比线程的执行时间还要长。那么如果程序一开始就创建好一个线程池,池中存放创建好的线程,用的时候从池中取,用完后返还,这样效率就会高很多。本文就重点讲解一下线程池的原理和使用。 正文 ...

欢迎来到Jimmy的博客 305

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

多线程原理及其使用总结

多线程原理及其使用总结 一,线程 1.线程及其调度 2.线程的使用语法 2.1Thread类 2.2 Runnable接口 3.线程的六种状态及其通信 3.1 Timed Waiting(计时等待) 3.2 BLOCKED(锁阻塞) 3.3 Waiting(无限等待) 3.4 状态综合关系 3.5 线程间通信 二.多线程 1.线程安全 1.1 安全问题: 1.2 线程同步 2.线程池 2.1 线程...

weixin_44747261的博客 1559

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

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

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

Java多线程之线程池详解

Java多线程之线程池详解 目录: 线程池使用及优势 线程池3个常用方式 线程池7大参数深入介绍 线程池底层工作原理 1. 线程池使用及优势 线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务, 如果线程数量超过了最大数量 超出数量的 线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。 它的主要特点为:线程复用,控制最大并发数,管...

努力努力再努力L 629

Java多线程、锁、线程池详解

通过本文的介绍,我们深入了解了Java中的多线程、锁机制、线程池的原理和应用。多线程可以提高程序的执行效率,但同时也带来了线程安全的问题。锁机制可以解决线程安全问题,而线程池则可以提高线程的复用率,减少线程创建和销毁的开销。理解这些概念的原理和应用可以帮助开发者编写高效、可靠的并发程序。希望本文能够帮助大家更好地理解和掌握Java中的多线程、锁和线程池,提升编程水平。

weixin_67825126的博客 2135

java多线程和线程池

目录 零、java线程理解 0.1 两种线程模型 0.1.1 用户级线程 ULT 0.1.2 内核级线程 KLT——JAVA虚拟机使用的线程模型(KLT) 0.2 java线程与系统内核线程 0.3 线程池的意义 0.4 线程 0.4.1线程五种状态 0.4.2 高并发下,线程池如何保证线程安全 0.4.3 多线程的使用场景 0.4.4 多线程的创建方式 0.4.4 多线程的停止 0.4.5控制多线程的运行顺序——join方法 一、线程池基本概念和使用示例 1.1 基本...

一直走,不要回头 8846

Java线程池详解

本文详细探讨了线程池在并发编程领域的应用,介绍了ThreadPoolExecutor的核心组件、工作原理,线程池的构造、拒绝策略、任务队列、线程池的监控、线程池工厂等相关内容,并讨论了线程池对系统性能和线程管理的优势。

qq_38875964的博客 2164

【Java多线程-2】Java线程池详解

java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类。 1 ThreadPoolExecutor概述 1.1 构造方法 在ThreadPoolExecutor类中提供了四个构造方法: public class ThreadPoolExecutor extends AbstractExecu...

云深不知处 4261

Java 线程池详解(一):线程池实现原理及使用

阿瑟东撒的

To be a great coder 2312

Java多线程案例之线程池

本篇文章将介绍多线程案例,线程池,线程在Linux中也叫做轻量级线程,尽管线程比进程较轻,但是如果线程的创建和销毁频率高了,开销也还是有的,为了进一步提高效率,引入了线程池,和字符串常量池类似,把线程提前创建好,放到一个“池子”里面,后面使用的时候,速度就快了,但是代价就是空间,线程池本质上也还是空间换时间。

未见花闻的博客 2133

Java线程池原理及四种线程池的使用

Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执

honghailiang的专栏 1万+

Java多线程实现之线程池详解

线程池在Java中是一种重要工具,用于管理和复用线程资源,合理使用线程池可以提高程序性能、减少资源消耗,并简化线程管理。本文我将详细介绍Java线程池的实现原理、常见类型以及使用方法等等,帮你更好地理解和深入Java的多线程实现

aa_hdkf_vg的博客 1935
上一篇: zookeeper Linux单机安装与springboot集成基本使用增删改查
下一篇: Java数据结构之双向链表实现
一个没有梦想的程序员
博客等级 码龄7年 20粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值