Java并发编程学习笔记(3)

8应用线程池

有些类型的任务需要明确指定一个执行策略,如依赖性任务、采用线程限制的任务,对响应时间敏感的任务、使用ThreadLocal的任务。(只有当线程本地thread_local()值的生命周期被限制在当前任务种时,在池的某线程中使用ThreadLocal才有意义;在线程池中,不应该使用ThreadLocal传递任务间的数值)

 

当任务都是同类的、独立时,线程池才有最佳的工作表现。

 

8.1线程饥饿死锁

在线程池中,如果一个任务依赖于其他任务的执行,就可能产生死锁。如:对于一个单线程化的Executor,一个任务将另一个任务提交到相同的Executor中,并等待提交的任务的结果,总会引起死锁。

第二个任务滞留在工作队列中,直到第一个任务完成;但第一个任务不会完成,因为它在等待第二个任务的完成。——这就是线程饥饿死锁。

 

因此,无论何时,提交一个非独立的Executor任务时,要明确出现线程饥饿死锁的可能性,且在代码或者配置文件以及其他可以配置Executor的地方,任何有关池的大小和配置约束都要写入文档。

 

8.1.2耗时操作

耗时任务会造成线程地堵塞,还会拖长服务时间。解决之道:限定任务的等待资源的时间。

 

大部分平台类库中的阻塞方法,同时提供了限时、非限时的2个版本,如Thread.join/BlockingQueue.put/CountDownLatch.await/Selector.select

 

8.2定制线程池大小

池的长度应该由某种配置机制来提供,不要硬编码,当然无须特别准确,只要以防过大或过小。

 

8.3配置ThreadPoolExcutor

核心池大小(Core Pool SIze)、最大池大小(max Pool Size)、存活时间(Keep Live Time)共同管理线程的创建与销毁。

 

核心池大小(Core Pool SIze)是目标的大小,线程池的实现试图维护池的大小:即没有任务执行,池的大小也等于核心池的大小;且直到工作队列充满时,池都不会创建更多的线程;

 

最大池大小(max Pool Size)是可同时活动的线程数的上限。如果一个线程已经闲置的时间超过了存活时间(Keep Live Time),会成为被回收的候选者,如果当前池的大小超过了核心池的大小,线程池会终止它。

 

Public ThreadPoolExecutor(int CorePoolSize,int maxPoolSize,long keepLiveTime,TimeUnit unit,……)

 

通过调节核心池的大小与存活时间,可以促进线程池归还空闲线程占有的资源。

 

newFixedThreadPool:工厂为请求的池设定了核心池的大小,最大池的大小,永不会超时;

newCachedThreadPool:工厂将最大池大小设置为Integer.MAX_VALUE,核心池大小为0,超时1分钟

 

8.3.2管理队列任务

ThreadPoolExecutor允许提供了一个BlockingQueue来持有等待执行的任务,任务排队有3种基本方法:无限队列,有限队列,同步移交。

 

newFixedThreadPool和newSingleThreadExecutor默认使用的是一个无限的LinkedBlockingQueue,如果所有的工作者线程都处于忙碌状态,任务将会在队列中等候;如果任务持续的快速到达,超过了它们被处理的速度,队列也会无限的增加。

 

稳妥的资源管理策略是使用有线的队列(如ArrayBlockingQueue、有限的LinkedBlockingQueue、PriorityBlockingQueue)

有界队列有助于避免资源耗尽的情况发生,但队列满时,要有相应的“饱和策略”处理。

 

newCachedThreadPool工厂提供了比定长的线程池更好的队列等候性能,它是Executor的一个很好的默认选择。

 

8.3.3饱和策略

当一个有线队列充满时,饱和策略开始生效。

ThreadPoolExecutor的饱和策略可以通过调用setRejectedExectionHandler来修改(如果任务提交到一个已经关闭的Executor时,也会用到饱和策略)

 

JDK提供了几种不同的RejectedExectionHandler实现,每一个实现不同的饱和策略:AbortPolicy、CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy.

 

默认的中止(abort)策略引起Executor抛出异常;调用者捕获异常,编写满足自己需求的处理代码;

当最新提交的任务不能进入队列等候执行时,“遗弃(Discard)”策略会放弃这个任务;

“遗弃最旧的(Discard——oldest)”策略选择丢弃的任务,是本应接下来执行的任务,该策略还会尝试重新提交新任务。(如果工作队列是优先级队列,那么遗弃最旧的策略选择丢弃的是刚好优先级最大的元素,所以混合使用遗弃最旧的饱和策略与优先级不可行)

 

“调用者运行(Call_runs)”策略的实现形式,既不会丢弃哪个任务,也不会抛出异常。它会把一些任务推回到调用者那里,以此缓解新任务流。它不会在线程池中执行最新的任务,但会在一个调用了executor的线程中执行。

 

8.3.4线程工厂

线程池创建线程,要通过一个线程工厂实现。默认的线程工厂创建了一个新的、非后台的线程。

ThreadFactory只有唯一的方法: .newThread()。它会在线程池需要创建一个新线程时调用。

 

8.4拓展ThreadPoolExecutor

它提供了几个“钩子”让子类去覆盖——beforeExecute、afterExecute、terminate——用于拓展ThreadPoolExecutor的行为。

(可以用于添加日志、时序、监视器、统计信息)

 

无论是正常从run返回,还是抛出异常,afterExecute会调用。

Terminate线程池关闭时调用。

 

Terminate可以用于释放Executor在生命周期中分配到的资源,还可以发出通知、记录日志、完成统计信息。

 

8.5并行递归算法

当每一个迭代彼此独立,且完成循环时,每个迭代的工作意义都足够大,足以弥补管理一个新任务的开销时,这个顺序循环是适合并行的。

 

9 GUI应用程序

几乎所有的GUI工具集都实现为“单线程化子系统”,意味着所有GUI的活动都被限制在一个单独的线程中,如Swing、SWT。

 

早期GUI:GUI事件在“主事件循环”进行处理;

现代GUI:创建一个专门的线程,事件派发线程EDI来处理GUI事件

(多线程GUI易受死锁影响)

 

单线程化的GUI框架通过线程限制来达到线程安全性,所有GUI中的对象,包括可视化组件和数据模型,都只能被事件线程访问。

 

Swing的线程限制

Swing的单线程规划:Swing的组件和模型只能在事件分派线程中被创建、修改和请求。

 

 

Java并发编程的艺术学习笔记 第一章 并发编程的挑战 并发编程的目的:为了让程序运行的更快。 但并不是启动的线程越多就能让程序最大限度地并发执行。 CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下一次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。 如何减少上下文切换? 1.无锁并发编程 2.CAS算法 3.使用最少线程 4.使用协程 避免死锁的常见方法? 1.避免一个线程同时获取多个锁 2.避免一个线程在 阅读详情

相关推荐

基于STM32与CAN总线的多电机协同控制系统设计与实现

本文详细介绍了基于STM32与CAN总线的多电机协同控制系统设计与实现。该系统采用分布式架构,通过CAN总线实现多节点通信,结合梯形加减速算法和同步控制策略,有效解决了工业自动化中多电机同步性差的问题。文章涵盖硬件设计、通信协议、抗干扰措施及实战调试经验,为工业应用提供高可靠性解决方案。

tech5的博客 969

《Java并发编程实战》学习笔记(3)

第四章:组合对象 设计线程安全的类 设计线程安全类的过程应该包括下面3个基本要素: 确定对象状态是由哪些变量构成的; 确定限制状态变量的不变约束; 制定一个管理并发访问对象状态的策略。 名词解释: 先验条件(precondition):针对方法(method),它规定了在调用该方法之前必须为真的条件。例如,你无法从空队列中移除一一个条目:在你删除元素前,队列必须处于“非空”状态。 后验条件(...

张育嘉的博客 399

Unity Shader Graph 2D - Procedural程序化图形转动的环状六边形

Hexagon又称六边形,在游戏中是十分常见的基础形状,本文将使用程序化的六边形来制作多个环状六边形叠加的转动动画效果,实践Unity Shader Graph中的常用节点功能。

Giver的博客 1928

【学习笔记】Java并发编程的艺术——第3章 Java内存模型

该规则保证了前一个操作对后一个操作是可见的1>程序顺序规则一个线程中的每个操作h-b于之后任意操作2>监视器锁规则解锁h-b于加锁3>volatile对于volatile写h-b于读4>传递性。

Lchen_kk的博客 1010

一文看懂英伟达A100、H100、A800、H800、H20

想要Deepseek私有化部署吗?无论是训练大型AI模型,还是进行高性能计算(HPC),还是Deepseek私有化部署,都需要强大的GPU支持。而英伟达(NVIDIA)作为全球领先的AI芯片制造商,推出了一系列高性能GPU,包括等,广泛应用于AI训练、推理、科学计算等领域。如果想搭建一个属于自己的算力中心,该如何选择合适的GPU?本文将带你详细了解这些GPU的特性,并指导你如何搭建算力中心。一、英伟达算力GPU系列解析1. A100:数据中心AI计算的奠基石:Ampere:6912:432。

【可全包】本人程序员,不需要做任何吹嘘,只是实在写点程序,写点文档,熟悉各类主流框架,SSM,SpringBoot,Flask,Djiango,Mysql,Sqlite,VUE,Uniapp等,各类程序设计专家,优质作者 2万+

20 CVPR Learning 3D Semantic Scene Graphs From 3D Indoor Reconstructions 学习笔记

3RScan是大规模真实世界的室内场景,特点是对478个自然改变的室内环境在不同的时间帧进行了1482 RGB-D scans,每一个scene都包括了一些位置被改变的物体。它和ScanNet数据集的区别主要在于ScanNet中的每一个采样环境都不相同,但是3RScan中存在采样环境相同但物体的位置不同的场景。Scene Graph Annotations 则是在3RScan的基础上给物体加入了场景图需要的关系、物体特征和类别标注,同时对3RScan进行了扩展,以此形成了场景图数据。

weixin_43508459的博客 1834

JAVA多线程并发编程学习笔记3——显式锁

JAVA并发编程 5. 显式锁 5.1 Lock接口 5.1.1 概念 Lock接口提供了无条件的、可轮询的、定时的、可中断的锁获取操作 加锁和解锁的方法都是显式的 优点:可以中断等待获取锁的线程;可以不必无限等待锁 5.1.2 方法 方法 返回值 描述 lock() void 申请锁,一直到锁可用 lockInterruptibly void 当前线程未被中断则申请锁,否则抛出异常 tryLock() boolean 只在调用时申请锁 tryLock(long, TimeU

WellsLau的博客 351

Go语言Gin框架项目:从零到一搭建一个用户管理系统

本文介绍了一个基于Go语言Gin框架开发的用户管理系统。系统采用MySQL数据库存储数据,使用Bootstrap 5构建现代化UI界面,实现了完整的CRUD功能。主要特点包括:RESTful API设计、前后端双重表单验证、实时搜索功能、SQL防注入措施以及响应式布局。项目结构清晰,包含数据库配置、用户模型、处理器和前端模板等模块。系统提供用户列表展示、新增/编辑表单、删除确认等功能,通过参数化查询确保安全性,并支持按姓名或邮箱搜索用户。

数据知道的博客 3994

offer来了(原理篇)学习笔记-第3章Java并发编程

Java并发编程 相对于传统的单线程,多线程能够在操作系统多核配置的基础上,能够更好地利用服务器的多个CPU资源,使程序运行起来更加高效。Java通过提供对多线程的支持来在一个进程内并发执行多个线程,每个线程都并行执行不同的任务,以满足编写高效率程序的要求。 Java线程的创建方法 常见的Java线程的4种创建方式分别为:1.继承Thread类、2.实现Runnable接口、3.Callable实现有返回值的线程和基于4.线程池ExecutorService。 继承Thread类: Thread类实现了R

thezapple的博客 537

UG\NX二次开发 判断对象是虚线还是实线

网友提问“怎么区分虚线实线”,这个可以通过函数判断。

王牌飞行员_里海的博客 357

全志F1C200S嵌入式驱动开发(lcd屏幕驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 lcd RGB屏幕作为比较经济、实用的显示工具,在实际场景中使用较多。它的信号来说,一般也比较简单,除了常规的数据信号,剩下来就是行同步、场同步、数据使能和时钟信号了。数据信号方面,常见的格式有RGB888、RGB666、RGB565。为什么有什么多选择,主要还是取决于soc pin脚的多少来定。当然,pin脚越多,显示的颜色就越精准,还原度就越高。 举例来说,假设

嵌入式-老费,一个分享专业嵌入式知识的blog 2792

Java并发编程学习——《Java Concurrency in Practice》学习笔记 3.对象的共享

3.1 可见性 在没有同步的情况下,编译器、处理器以及运行时都可能对操作的执行顺序进行一些意想不到的调整。因为它们会对代码的执行顺序进行“重排序”。在缺乏足够同步的多线程程序中,要想对内存操作的执行顺序进行判断,几乎无法得出正确的结论。 重排序 重排序指的是编译器和处理器为了优化程序性能而对指令序列进行重新排序的手段 重排序主要分为两类:编译器优化的重排序、指令级别并行的重排...

在咖啡里溺水的鱼 500

廖雪峰Python教程[完整版]

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

《Java并发编程实战》学习笔记之 第3章 对象的共享

1.内存可见性     synchronized关键字同步有两方面的作用:  (1)实现原子性或者确定临界区 (2)确保内存可见性 所谓内存可见性,即当一个线程修改了对象状态后,其他线程能够看到修改后的状态。      多线程程序在没有同步的情况下,编译器、处理器及运行时等都可能对操作执行顺序进行一些意想不到的调整。在缺乏足够同步的多线程程序中,要想对内存操作的执行顺序进行判断,几乎...

austboy123的博客 184

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

怀旧版电脑GBC模拟器

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

java并发编程学习笔记(3):java内存模型(JMM)

语法: CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型 BEGIN 函数体 END 注:1.参数列表包含两部分:参数名和参数类型 2.函数体:必须有return语句,否则会报错。 3.若函数体中仅有一条语句,则可以省略BEGIN END 4.使用delimiter语句设置结束标记 ...

光脚小孩的博客 371

STM32F407中文手册

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

《Java 并发编程实战》学习笔记一

多核时代每颗 CPU 都有自己的缓存,这时 CPU 缓存(三级缓存)与内存的数据一致性就容易出现问题了,当多个线程在不同的 CPU 上执行时,这些线程操作的是不同的 CPU 缓存。比如,线程 A 操作的是 CPU-1 上的缓存,而线程 B 操作的是 CPU-2 上的缓存,很明显,这个时候线程 A 对变量 V 的操作对于线程 B 而言就不具备可见性了。:高级语言里一条语句往往需要多条 CPU 指令完成,例如count += 1这句代码,至少需要三条 CPU 指令。

yibushao的博客 1152

【极客时间】《Java并发编程实战》学习笔记

【极客时间】《Java并发编程实战》学习笔记

Mr.Cui的Java学习之路 2648

学习笔记:Java 并发编程②_管程

本博客内容:共享问题分析;synchroinzed;线程安全分析;Monitor;wait / notify;Park / Unpark;分析线程状态的转换;活跃性;ReentrantLock。

做笔记,记录学习中遇到的问题。 1741

【Java 并发编程】详解

在并发编程中,使用普通的集合类(如 ArrayList、HashMap 等)往往会出现线程安全问题,因为它们在设计时并没有考虑多线程并发访问的情况。Java 提供了一系列并发容器来解决这个问题,这些并发容器在保证高效性能的同时,能够支持多线程安全地进行读写等操作。

架构师之路 1123

【目标设定】Java 并发编程

1. 目标是什么 掌握Java并发编程的使用 掌握Java并发编程的原理 阅读《Java并发编程的艺术》 阅读《Java并发编程实战》 输出 学习笔记5 篇及以上 2. 完成目标有什么好处 习得Java并发编程技能 补充技能树的技能点 3. 计划多长时间完成目标 2019/10/15 - 2019/11/15 4. 完成目标的途中有哪些障碍 没有时间学习 被其他的学习目标吸引 5....

Penn的博客 138

JAVA并发编程总结

总结JDK提供的并发类的玩法和陌生概念和注意事项,也是自己总结的java并发经验

qq_44769557的博客 2116

【免费下载】 探索Java并发编程的奥秘:《JAVA并发编程艺术》高清PDF下载

探索Java并发编程的奥秘:《JAVA并发编程艺术》高清PDF下载 【下载地址】JAVA并发编程艺术高清PDF下载 本仓库提供了一份名为《JAVA并发编程艺术》的高清PDF文件下载。该资源详细介绍了Java并发编程的各个方面,涵盖了从基础概念到高级技术的全面内容 ...

gitblog_06678的博客 1161

如何学习Java并发编程

2012年我刚转行到互联网,那年夏天我从传统通信行业跳槽到互联网行业。那是我成年后看的第一部国产动画片,可谓惊为天人。里面有所谓的八奇技,其中有一门绝技称为:术之尽头,炁体源流。虽然目前作者还没有揭开谜底,但从定义上来说,炁体源流大概有“追本溯源,回归本质”的含义。为什么扯这些呢?很多人学不好Java并发编程,恰恰是因为没有抓住本质。

smart_an的专栏 1484

《Java并发编程的艺术》之 Java并发编程基础

《Java并发编程的艺术》之 Java并发编程基础 文章目录《Java并发编程的艺术》之 Java并发编程基础线程简介什么是线程代码清单4-1 MultiThread.java解析为什么要使用多线程更多的处理器核心更快的响应时间线程优先级代码清单4-2 Priority.java结果注意参数解析线程的状态注意Daemon线程注意注意启动和终止线程构造线程代码清单4-6 Thread.java启动线程注意理解中断代码清单4-7 Interrupted.java过期的suspend()、resume()和sto

weixin_44019182的博客 2495

Java并发编程实践

并发编程是指通过设计和实现多线程程序来利用计算机资源和提高程序执行效率的编程方法。它的主要特点是多线程之间的竞争和协作关系。线程安全性是指并发编程中,在多个线程访问共享数据时,对数据的访问不会产生意料之外的后果。实现线程安全性需要从数据的状态变化过程进行分析,并采用相应的线程安全策略。

BXA 2996

学习笔记:Java 并发编程④_无锁

本章内容:CAS 与 volatile;CAS 的相关 API:原子整数、原子引用、原子累加器;Unsafe。

做笔记,记录学习中遇到的问题。 1439
上一篇: Java并发编程学习笔记(2)
下一篇: Java并发编程学习笔记(4)
hebeind100
博客等级 码龄17年 119粉丝 1372原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值