Java 多线程设计模式之 Single Threades Execution

黑洞暗物质环境对时空结构与引力波的影响 在广义相对论中,黑洞周围的时空结构受暗物质分布影响显著。通过爱因斯坦簇模型可以量化这种效应,该模型通过无相互作用粒子壳层模拟暗物质晕,精确求解爱因斯坦场方程。暗物质密度剖面(如Hernquist、NFW、Jaffe模型)会改变黑洞周围的光环位置和ISCO动力学,进而影响引力波信号和X射线辐射谱。这些效应在下一代引力波探测器(如LISA)和X射线干涉仪(如Lynx)中有望被观测到,为研究暗物质性质提供新途径。 阅读详情

Single Threades Execution 模式

所谓 Single Threades Execution 模式,意即“以一个线程执行”。就像独木桥同一时间内只允许一个人通行一样,该模式用于设置限制,以确保同一时间内只能让一个线程执行处理。

Demo

不使用 Single Threades Execution 模式的程序

使用程序模拟三个人频繁地通过一个只允许一个人经过的门情形。当人们通过门的时候,统计人数便会递增。另外程序还会记录通行者的“姓名和出生地”

类一览表

名字说明

Main创建门,并让三个人不断地通过的类

Gate表示门的类。它会在人们通过门时记录其姓名与出生地

UserThread表示人的类。人们不断地通过门

// Main.javapublicclassMain{publicstaticvoidmain(String[] args){        Gate gate =newGate();newUserThread(gate,"Bob","Britain").start();newUserThread(gate,"Cao","China").start();newUserThread(gate,"Uber","USA").start();    }}复制代码

// Gate.javapublicclassGate{privateintcounter =0;privateString name ="Nobody";privateString address ="NoWhere";publicvoidpass(String name, String address){this.counter++;this.name = name;this.address = address;        check();    }privatevoidcheck(){if(this.name.charAt(0) !=this.address.charAt(0)) {            System.out.println("******** BROKEN ********** : "+ toString());        }    }@OverridepublicStringtoString(){return"No. "+this.counter +" : "+this.name +" , "+this.address;    }}复制代码

// UserThread.javapublicclassUserThreadextendsThread{privatefinalGate gate;privatefinalString name;privatefinalString address;publicUserThread(Gate gate, String name, String address){this.gate = gate;this.name = name;this.address = address;    }@Overridepublicvoidrun(){        System.out.println(this.name +" BEGIN");while(true) {            gate.pass(this.name,this.address);        }    }}复制代码

当这个程序执行时,时间点不同,生成的结果也会不一样,以下是打印出来的 log

Bob BEGINCao BEGIN******** BROKEN ********** : No. 59622 : Bob , BritainUber BEGIN******** BROKEN ********** : No. 77170 : Uber , USA******** BROKEN ********** : No. 89771 : Uber , USA******** BROKEN ********** : No. 93128 : Cao , China******** BROKEN ********** : No. 95654 : Uber , USA******** BROKEN ********** : No. 98440 : Cao , China******** BROKEN ********** : No. 102283 : Cao , China******** BROKEN ********** : No. 104491 : Cao , China******** BROKEN ********** : No. 106791 : Uber , USA******** BROKEN ********** : No. 110022 : Uber , USA******** BROKEN ********** : No. 112073 : Uber , USA******** BROKEN ********** : No. 113973 : Uber , USA******** BROKEN ********** : No. 77170 : Uber , USA******** BROKEN ********** : No. 116050 : Bob , China******** BROKEN ********** : No. 117334 : Bob , Britain******** BROKEN ********** : No. 119992 : Bob , USA******** BROKEN ********** : No. 124427 : Uber , USA******** BROKEN ********** : No. 117152 : Bob , Britain******** BROKEN ********** : No. 129298 : Bob , China******** BROKEN ********** : No. 130552 : Cao , Britain******** BROKEN ********** : No. 147176 : Cao , China******** BROKEN ********** : No. 148546 : Uber , USA复制代码

通过 log 可以知道运行结果与预期不一致,所以说 Gate 类是不安全的,是非线程安全类。

如果仔细看一下 counter 的值,最开始显示 BROKEN 的时候,counter 的值已经变为了 59622。也就是说,在检察处第一个错误的时候 Gate 的 pass 方法已经运行了 5 万多次了。在这里,因为 UserThread 类的 run 方法执行的是无限循环,所以才检查除了错误。但是如果只测试几次,是根本找不出错误的。

这就是多线程程序设计的难点之一。如果检察出错误,那么说明程序并不安全。但是就算没有检察出错误,也不能说程序就一定是安全的。

调试信息也不可靠

仔细看 log 会发现还有一个奇怪的现象,比如:

******** BROKEN ********** : No. 59622 : Bob , Britain复制代码

虽然此处输出了 BROKEN 信息,但是姓名和出生地首字母是一样的。尽管显示了 BROKEN,但是调试信息好像并没有错。

导致这种现象的原因是,在某个线程执行 check 方法时,其他线程不断执行 pass 方法,改谢了 name 字段和 address 字段的值。

这也是多线程程序设计的难点之一。如果显示调试信息的代码本身就是非线程安全的,那么显示的调试信息就很可能是错误的。

如果连操作测试和调试信息都无法确保安全性,那就进行代码评审吧。多个人一起仔细阅读代码,确认是否会发生问题,这是确保程序安全性的一个有效方法。

修改 Gate 类使其线程安全

// Gate.javapublicclassGate{    ...publicsynchronizedvoidpass(String name, String address){this.counter++;this.name = name;this.address = address;        check();    }        ...}复制代码

之后程序就可以正常的运行,也不在打印 BROKEN 的 log 信息了

Single Threaded Execution 模式归纳

SharedResource 共享资源

在刚才的示例中,Gate 类扮演 SharedResource 的角色

SharedResource 角色是可被多个线程访问的类,包含很多方法,但这些方法主要分为如下两类:

safeMethod: 多个线程同时调用也不会发生问题的方法

unsafeMethod:多个线程同时调用会发生问题,因此必须加以保护的方法

而 unsafeMethod 在被多个线程同时执行时,实例状态有可能发生分歧。这时就需要保护该方法,使其不被多个线程同时访问。Java 则是通过将 unsafeMethod 声明为 synchronized 方法来进行保护

死锁

在该模式下,满足下列条件时,死锁就会发生

存在多个 SharedResource 角色

线程在持有着某个 SharedResource 角色锁的同时,还想获取其他 SharedResource 角色的锁

获取 SharedResource 角色的锁的顺序并不固定

原子操作

不可分割的操作通常称为原子操作。

上述示例中 Gate类是线程安全的 我们将 pass 声明为了 synchronized 方法,这样 pass 方法也就成为了原子操作

Java 编程规范中定义了一些原子操作。例如 char、int 等基本类型的赋值和引用操作都是原子的。另外,对象等引用类型的赋值和引用操作也是原子的。由于本身就是原子的,所以就算不加上 synchronized,这些操作也不会被分割。但是 long、double 的赋值和引用操作并不是原子的

总结如下:

基本类型、引用类型的赋值和引用是原子操作

但 long 和 double 的赋值和引用是非原子操作

long 或 double 在线程间共享时,需要将其放入 synchronized 中操作,或者声明为 volatile

计数信号量和 Semaphore 类

上面介绍 Single Threaded Execution 模式用于确保某个区域“只能由一个线程”执行。下面我们将这种模式进一步扩展,以确保某个区域“最多只能由 N 个线程”执行。这时就要用计数信号量来控制线程数量。

java.util.concurrent 包提供了表示计数信号量的 Semaphore 类

资源的许可个数将通过 Semaphore 的构造函数来指定

Semaphore 的 acquire 方法用于确保存在可用资源。当存在可用资源时,线程会立即从 acquire 方法返回,同时信号量内部的资源个数会减 1 。 如无可用资源,线程阻塞在 acquire 方法内,直至出现可用资源。

Semaphore 的 release 方法用于释放资源。释放资源后,信号量内部的资源个数会增加 1。另外如果 acquire 中存在等待的线程,那么其中一个线程会被唤醒,并从 acquire 方法返回。

示例

// BoundedResource.javapublicclassBoundedResource{privatefinalintpermits;privatefinalSemaphore semaphore;privatefinalRandom random =newRandom(314159);publicBoundedResource(intpermits){this.semaphore =newSemaphore(permits);this.permits = permits;    }publicvoiduse()throwsInterruptedException{try{this.semaphore.acquire();            doUse();        }finally{this.semaphore.release();        }    }privatevoiddoUse()throwsInterruptedException{        System.out.println(Thread.currentThread().getName() +" : BEGIN used = "+ (this.permits -this.semaphore.availablePermits()));        Thread.sleep(this.random.nextInt(500));        System.out.println(Thread.currentThread().getName() +" : END used = "+ (this.permits -this.semaphore.availablePermits()));    }}复制代码

// SemaphoreThread.javapublicclassSemaphoreThreadextendsThread{privatefinalRandom random =newRandom(26535);privatefinalBoundedResource resource;publicSemaphoreThread(BoundedResource resource){this.resource = resource;    }@Overridepublicvoidrun(){try{while(true) {this.resource.use();                Thread.sleep(this.random.nextInt(2000));            }        }catch(InterruptedException e) {            e.printStackTrace();        }    }}复制代码

// Main.javapublicclassMain{publicstaticvoidmain(String[] args){        BoundedResource boundedResource =newBoundedResource(3);newSemaphoreThread(boundedResource).start();newSemaphoreThread(boundedResource).start();newSemaphoreThread(boundedResource).start();    }}复制代码

打印结果:

Thread-0 : BEGIN used = 2

Thread-2 : BEGIN used = 3

Thread-1 : BEGIN used = 2

Thread-2 : END used = 3

Thread-1 : END used = 2

Thread-0 : END used = 1

Thread-2 : BEGIN used = 1

Thread-2 : END used = 1

Thread-1 : BEGIN used = 1

Thread-0 : BEGIN used = 2

Thread-1 : END used = 2

Thread-0 : END used = 1

Thread-2 : BEGIN used = 1

Thread-2 : END used = 1

Thread-1 : BEGIN used = 1

Thread-0 : BEGIN used = 2

Thread-2 : BEGIN used = 3

Thread-0 : END used = 3


进群:可以领取免费的架构师学习资料。

进群:了解最新的学习动态

进群:了解最新的阿里,京东招聘资讯

进群:获取更多的面试资料

1、具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。

2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。

3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加群。

4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加群。

5. 群号:835638062 点击链接加入群:https://jq.qq.com/?_wv=1027&k=5S3kL3v

6.阿里Java高级大牛直播讲解知识点,分享知识,上面五大专题都是各位老师多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!

XTDrone——ALOAM与3D激光雷达三维SLAM(处理没有点云和坐标系报错的问题) 本文介绍了XTDrone中配置如何在三维环境中使用A-LOAM算法配合velodyneHDL32激光雷达包括依赖包安装、代码修改和PX4系统配置,以及相关报错细节的注意事项。 阅读详情

相关推荐

语言 拉丁超立方抽样_医学统计与R语言:间断时间序列分析(Interrupted time series regression)...

微信公众号:医学统计与R语言如果你觉得对你有帮助,欢迎转发Interrupted time series (ITS) analysis is a valuable study design for evaluating the effectiveness of population-level health interventions that have been implemented...

weixin_29300805的博客 3706

深入学习Java中的线程池

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。创建自定义线程池,参数可自定义配置。:线程池的基本大小,即在没有任务需要执行的时候线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程。

摸鱼胖嘟嘟的博客 1681

AgentVerse实战:构建多智能体协作系统的关键技术与应用场景

本文深入探讨了AgentVerse框架在构建多智能体协作系统中的关键技术及应用场景。通过分析智能体通信协议、环境交互机制和任务分解算法,展示了如何利用大型语言模型(LLM)实现智能体间的专业化分工与动态协作。文章还提供了智能软件开发团队和智能客服系统等典型应用案例,以及部署优化实践,为开发者构建高效的多智能体系统提供实用指导。

weixin_29254029的博客 361

java8 singlethread_【Concurrent】JDK8线程池(一次记不住就收藏下来慢慢看吧!)

java线程的创建、销毁和线程减切换是一件比较耗费计算机资源的事。如果我们需要用多线程处理任务,并频繁的创建、销毁线程会造成计算机资源的无端浪费,因此出现了线程池技术。三条使用线程池的好处:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源...

weixin_39671509的博客 297

实战解析:如何利用MDFEND与Weibo21数据集构建多领域假新闻检测系统

本文实战解析了如何利用MDFEND模型与Weibo21数据集构建多领域假新闻检测系统。文章深入剖析了MDFEND的领域门控与专家混合机制,并提供了从数据预处理、模型理解到训练部署的完整指南,旨在解决通用模型在不同领域新闻检测中的性能衰减问题,提升检测的准确性与适应性。

vulkan6gpu的博客 582

告别报错!Win10下Autodock Vina 1.2.3保姆级安装与避坑指南

本文提供了Win10系统下Autodock Vina 1.2.3的完整安装与实战指南,涵盖环境配置、分子文件预处理、对接参数优化及结果分析等关键步骤。通过详细的避坑技巧和优化方案,帮助用户高效完成分子对接任务,特别适合生物信息学研究人员和药物发现领域的初学者。

weixin_29969209的博客 408

java单线程single_JavasingleThreadinserver(java服务器单线程

原文链接【出处】:http://tutorials.jenkov.com/java-multithreaded-servers/singlethreaded-server.htmlSinglethreaded Server in JavaJakob JenkovLast update: 2017-11-01Thistext will show how to implement a singleth...

weixin_39608301的博客 164

华为OD机试真题 新系统2026-04-01 Java&Go【计算数列位置N的值】

如果其前面的M个元素中,存在值相同的元素,则该位置上的数值等于前面M个数中最大的数值与最小的数值之如果其前面的M个元素中,不存在值相同的元素,则该位置上的数值等于前面M个数中最大的数值与最小的数值之差;1、输入M、N两个数,则按照以下规则形成一个数列;两个整数,用逗号分割,分别表示M和N。一个整数,表示数列第N个位置上的数值。2、数列的前M个元素的值为1到M;请计算该数列第N个位置上的数值。N取值范围:1<= N<=50。M取值范围:3<=M<=10。

MISAYAONE的博客 2076

java单线程single_Java多线程基础(三)——Single Threaded Execution模式

一、定义Single Threaded Execution 是指“以1个线程执行”的意思,有时也称为Critical Section(临界区)。二、模式案例案例:假设有三个人,频繁地通过一扇门,规定每次只能通过一个人,当通过一个人时,程序会将通过的总人次加1,同时记录该次通过人的姓名和出生地。门的定义:public class Gate {private int counter = 0;priva...

weixin_39715187的博客 284

uniapp(全端兼容) - 最新详细实现支付键盘功能组件,从底部弹出数字键盘输入支付密码进行付款交互效果,自定义支付密码键盘仿微信、支付宝支付键盘,1~9密码数字键盘,电商支付(详细示例代码复制运行

uniapp,微信小程序,自定义数字键盘,输入支付密码的键盘组件,uniapp小程序如何实现从底部弹出输入支付密码自定义键盘功能,uniapp小程序密码支付键盘组件插件,自定义数字键盘输入页面,怎么封装底部弹窗自定义数字键盘用于输入支付密码,uniapp小程序仿类似电商支付密码输入模态框,uniapp微信小程序平台实现自定义支付密码键盘,uniapp 密码支付,数字键盘,安全键盘,交易键盘,交易密码,交易密码输入框,uniapp自定义支付键盘: uniapp自定义支付键盘,uniapp小程序端实现键盘输入支

✅ 精选推荐文章 2907

【WRF-GHG 教程第一期】概述(Overview)

概述(Overview)

WW、forever的博客 513

java single threaded_Java 多线程设计模式之 Single Threades Execution

Single Threades Execution 模式所谓 Single Threades Execution 模式,意即“以一个线程执行”。就像独木桥同一时间内只允许一个人通行一样,该模式用于设置限制,以确保同一时间内只能让一个线程执行处理。Demo不使用 Single Threades Execution 模式的程序使用程序模拟三个人频繁地通过一个只允许一个人经过的门情形。当人们通过门的时候...

weixin_39835147的博客 163

Hermes Agent 对阵 OpenClaw:自我改进的 AI 队友

但在 2026 年 2 月,Nous Research 发布了 Hermes Agent,它带来了不同的愿景:一个不仅能够运行,还能学习的代理。在完成复杂的多步骤任务后,它会分析自己的操作并创建一个可复用的技能。对于已在使用 OpenClaw 的澳大利亚企业而言,这意味着您可以试用 Hermes Agent,而无需丢失数月的配置和自定义成果。最重要的区别在于理念:OpenClaw 是一个需要配置的工具,而 Hermes Agent 则是一个会学习的队友。OpenClaw 的技能是静态的。

xiaoshun007的专栏 1572

java 单线程_实例分析Java单线程与多线程

线程:每一个任务称为一个线程,线程不能独立的存在,它必须是进程的一部分单线程:般常见的Java应用程序都是单线程的,比如运行helloworld的程序时,会启动jvm进程,然后运行main方法产生线程,main方法也被称为主线程。多线程:同时运行一个以上线程的程序称为多线程程序,多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。单线程代码例子:public class Single...

weixin_39968128的博客 340

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

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

java线程single_多线程-SingleThreadExecu中出现java.util.concurrent.RejectedExecutionException的可能原因是什么?...

我在单例中创建以下执行程序:final private ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {final ThreadFactory delegate = Executors.defaultThreadFactory();public Thread newThread(Ru...

weixin_42327217的博客 403

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

JAVA 线程池SingleThreadExecutor实践教程

是一个单线程的Executor,它使用单个工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。下面是使用。

guanglihuan的专栏 1376

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

JAVA多线程(二十一)Java多线程之SingleThreadExecutor单线程化线程池

1.JAVA多线程(二十一)Java多线程之SingleThreadExecutor单线程化线程池 1.1 单线程化线程池SingleThreadExecutor    SingleThreadExecutor 是只有一个线程的线程池。通过源代码查看SingleThreadExecutor实现: /** * Creates an Executor that uses a sing...

yuan_xw的专栏 1413

java单线程single_SingleThreadExecutor单线程线程池

package com.jiading.pool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class singleThreadTest {public static void main(String[] args) {/*** JAVA通过Executors提...

weixin_39638057的博客 690

Java 线程池 SingleThreadExecutor的使用及示例代码

Java 线程池 SingleThreadExecutor是Executors封装好的4种常见的功能线程池之一,它是只有核心线程的单线程的线程池,可以确保所有任务按照指定的顺序在一个线程中执行。本文主要介绍 SingleThreadExecutor的使用及示例代码。 原文地址:Java 线程池 SingleThreadExecutor的使用及示例代码 ...

m0_60105488的博客 520

single thread execution线程设计模式学习

概念        single thread execution 即“以一个线程执行”。就像独木桥同一时间只允许一个人通行一样,该模式主要用于限制,以确保同一时间内只能让一个线程执行处理。 实现        主要使用synchronized关键字实现。 角...

qq_35300804的博客 285

多线程:Single Thread Execution

多线程、Single Thread Execution

肃林的博客 474

java多线程设计模式之-SingleThreadExecution模式

之前学习的程序大多是单个线程运行,不会涉及到多个线程之间的通信以及多个线程之间的相互影响,按照之间的面向对象的设计方法,我们可以模拟一个场景,当我们进出门口的程序,进出门口时需要记录这个人的姓名和出生地(模拟用例):    设计一个“门”类,用于记录进出口的人员,代码编写如下: public class Gate { private int counter = 0; private Str

Cherish__it的博客 852

SingleThreadExecutor详解

SingleThreadExecutor是使用单个worker线程的Executor。下面是SingleThreadExecutor的源代码实现。 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecut...

YK的博客 5650
上一篇: Java 8 中的 Streams API 详解
下一篇: 网易云音乐数据交互—async&await实现版
普通网友
博客等级 码龄8年 55粉丝 197原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值