Java多线程——对象的组合

设计线程安全的类

  • 找出构成对象状态的所有变量
  • 找出约束状态变量的不变性条件
  • 建立对象状态的并发访问管理策略

实例封闭

当一个对象被封装到另一个对象中,能够访问被封装对象的所有代码路径都是已知的。

通过封闭和加锁,可以确保以线程安全的方式使用非线程安全的对象

class MutablePoint {public int x, y;public MutablePoint() {x = 0;y = 0;}public MutablePoint(MutablePoint p) {this.x = p.x;this.y = p.y;}
}

将MutablePoint封闭到MonitorVehicleTracker,返回对象通过拷贝生成新的对象,并对get和set加锁

class MonitorVehicleTracker {@GuardedBy("this")private final Map<String, MutablePoint> locations;public MonitorVehicleTracker(Map<String, MutablePoint> locations) {this.locations = deepCopy(locations);}public synchronized Map<String, MutablePoint> getLocations() {return deepCopy(locations);}public synchronized MutablePoint getLocation(String id) {MutablePoint loc = locations.get(id);return loc == null ? null : new MutablePoint(loc);}public synchronized void setLocation(String id, int x, int y) {MutablePoint loc = locations.get(id);if (loc == null)throw new IllegalArgumentException("No such ID:" + id);loc.x = x;loc.y = y;}private static Map<String, MutablePoint> deepCopy(Map<String, MutablePoint> m) {Map<String, MutablePoint> result = new HashMap<String, MutablePoint>();for (String id : m.keySet())result.put(id, new MutablePoint(m.get(id)));return Collections.unmodifiableMap(result);}
}

但数据量大时,每次拷贝会降低性能

线程安全性的委托

将域声明为final变成不可变对象

class Point {public final int x, y;public Point(int x, int y) {this.x = x;this.y = y;}
}

将线程安全委托给ConcurrentMap,返回实时更新且只读的对象引用

class DelegatingVehicleTracker {private final ConcurrentMap<String, Point> locations;private final Map<String, Point> unmodifiableMap;public DelegatingVehicleTracker(Map<String, Point> points) {locations = new ConcurrentHashMap<String, Point>(points);unmodifiableMap = Collections.unmodifiableMap(locations);}public Map<String, Point> getLocations() {return unmodifiableMap;}public Point getLocation(String id) {return locations.get(id);}public void setLocation(String id, int x, int y) {if (locations.replace(id, new Point(x, y)) == null)throw new IllegalArgumentException("invalid vehicle name:" + id);}
}

若需要非实时更新且只读的对象引用,因为map内容是不可变的,可以浅拷贝

public Map<String, Point> getLocations() {return Collections.unmodifiableMap(new HashMap<>(locations));
}

若想要可变且线程安全的Point类,需要注意get应该同时获得x和y,若分别提供的话,可能会在两次调用中导致状态不一致

class SafePoint {@GuardedBy("this")private int x, y;private SafePoint(int[] a) {this(a[0], a[1]);}public SafePoint(SafePoint p) {this(p.get());}public SafePoint(int x, int y) {this.x = x;this.y = y;}public synchronized int[] get() {return new int[]{x, y};}public synchronized void set(int x, int y) {this.x = x;this.y = y;}
}
class PublishingVehicleTracker {private final Map<String, SafePoint> locations;private final Map<String, SafePoint> unmodifiableMap;public PublishingVehicleTracker(Map<String, SafePoint> locations) {this.locations = new ConcurrentHashMap<String, SafePoint>(locations);this.unmodifiableMap = Collections.unmodifiableMap(this.locations);}public Map<String, SafePoint> getLocations() {return unmodifiableMap;}public SafePoint getLocation(String id) {return locations.get(id);}public void setLocation(String id, int x, int y) {if (!locations.containsKey(id))throw new IllegalArgumentException("invalid vehicle name:" + id);locations.get(id).set(x, y);}
}

在现有的线程安全类中添加功能

最简单的方法是修改原始类,若没有源代码通过扩展实现,如下实现putIfAbsent()

class BetterVector<E> extends Vector<E> {public synchronized boolean putIfAbsent(E x) {boolean absent = !contains(x);if (absent)add(x);return absent;}
}

但如果底层的类改变了同步策略并选择了不同的锁来保护它的状态变量,那么子类会被破坏

客户端加锁机制

客户端加锁是指,对于使用某个对象X的客户端代码,使用X本身用于保护其状态的锁来保护这段客户代码

对于由Collections.synchronizedList封装的ArrayList等类,可通过辅助类

class ListHelper<E> {public List<E> list = Collections.synchronizedList(new ArrayList<>());public boolean putIfAbsent(E x) {boolean absent = !list.contains(x);if (absent)list.add(x);return absent;}
}

但上面的做法是错误的,因为synchronizedList内部的锁和ListHelper的锁不是同一个

class ListHelper<E> {public List<E> list = Collections.synchronizedList(new ArrayList<>());public boolean putIfAbsent(E x) {synchronized (list) {boolean absent = !list.contains(x);if (absent)list.add(x);return absent;}}
}

但会将类的加锁代码放到与其完全无关的其他类中,会破坏同步策略的封装性

组合

将操作委托给底层的list,并新增加锁方法

class ImprovedList<T> implements List<T> {private final List<T> list;public ImprovedList(List<T> list) {this.list = list;}public synchronized boolean putIfAbsent(T x) {boolean absent = !list.contains(x);if (absent)list.add(x);return absent;}//......
}

通过自身的内置锁增加了一层额外的加锁,即使List不是线程安全的或者修改了它的加锁实现,ImprovedList仍是线程安全的

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

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

相关文章

在K8S中,如何把某个worker节点设置为不可调度?

在Kubernetes中&#xff0c;如果你想要把一个worker节点设置为不可调度&#xff0c;意味着你不想让Kubernetes调度器在这个节点上调度新的Pod。这通常用于维护或升级节点&#xff0c;或者当节点遇到硬件故障或性能问题时&#xff0c;要将某个worker节点设置为不可调度。 方法1…

计算图 Compute Graph 和自动求导 Autograd | PyTorch 深度学习实战

前一篇文章&#xff0c;Tensor 基本操作5 device 管理&#xff0c;使用 GPU 设备 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started PyTorch 计算图和 Autograd 微积分之于机器学习Computational Graphs 计算图Autograd…

探秘Linux IO虚拟化:virtio的奇幻之旅

在当今数字化时代&#xff0c;虚拟化技术早已成为推动计算机领域发展的重要力量。想象一下&#xff0c;一台物理主机上能同时运行多个相互隔离的虚拟机&#xff0c;每个虚拟机都仿佛拥有自己独立的硬件资源&#xff0c;这一切是如何实现的呢&#xff1f;今天&#xff0c;就让我…

Mac本地部署DeekSeek-R1下载太慢怎么办?

Ubuntu 24 本地安装DeekSeek-R1 在命令行先安装ollama curl -fsSL https://ollama.com/install.sh | sh 下载太慢&#xff0c;使用讯雷&#xff0c;mac版下载链接 https://ollama.com/download/Ollama-darwin.zip 进入网站 deepseek-r1:8b&#xff0c;看内存大小4G就8B模型 …

Spring 面试题【每日20道】【其二】

1、Spring MVC 具体的工作原理&#xff1f; 中等 Spring MVC 是 Spring 框架的一部分&#xff0c;专门用于构建基于Java的Web应用程序。它采用模型-视图-控制器&#xff08;MVC&#xff09;架构模式&#xff0c;有助于分离应用程序的不同方面&#xff0c;如输入逻辑、业务逻辑…

基于UKF-IMM无迹卡尔曼滤波与交互式多模型的轨迹跟踪算法matlab仿真,对比EKF-IMM和UKF

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于UKF-IMM无迹卡尔曼滤波与交互式多模型的轨迹跟踪算法matlab仿真,对比EKF-IMM和UKF。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 .…

用FormLinker实现自动调整数据格式,批量导入微软表单

每天早上打开Excel时&#xff0c;你是否也经历过这样的噩梦&#xff1f; 熬夜调整好的问卷格式&#xff0c;导入微软表单后全乱套 客户发来的PDF反馈表&#xff0c;手动录入3小时才完成10% 200道题库要转为在线测试&#xff0c;复制粘贴到手指抽筋 微软官方数据显示&#xf…

opencv图像处理框架

一.课程简介与环境配置 二.图像基本操作 (1)计算机眼中的视觉 1)计算机眼中图像是由一块块组成&#xff0c;每一块又由很多很多个像素点组成&#xff0c;一个像素点的值是在0到255之间&#xff0c;值越大就越亮。 2)RGB表示彩色图像的三个颜色通道(红绿蓝)&#xff0c;一张…

【自学笔记】JavaWeb的重点知识点-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 JavaWeb知识点一、基础概念二、项目结构三、Tomcat服务器四、数据库连接&#xff08;JDBC&#xff09;五、前端技术六、高级技术 总结 以下是JavaWeb知识点的MD格式…

前端架构师的职责之我见

我觉得前端架构师的职责有下面几点&#xff1a; 从全局的角度来看待技术需求和实施技术应用。通过架构设计和模式使用及基础设施建设来赋能开发工作。通过影响和示范来提升团队成员用技术手段解决问题的意识和能力。 下面具体解释一下&#xff1a; 从全局的角度来看待技术需…

PWN--格式化字符串

简介 ‌格式化字符串‌是指在编程过程中&#xff0c;通过特殊的占位符将相关对应的信息整合或提取的规则字符串。格式化字符串包括格式化输入和格式化输出&#xff0c;其本质是程序员调用相关格式化字符串的操作协议规定。错误的或不当的信息配置可能导致程序运行失效或产生未…

基于脉冲响应不变法的IIR滤波器设计与MATLAB实现

一、设计原理 脉冲响应不变法是一种将模拟滤波器转换为数字滤波器的经典方法。其核心思想是通过对模拟滤波器的冲激响应进行等间隔采样来获得数字滤波器的单位脉冲响应。 设计步骤&#xff1a; 确定数字滤波器性能指标 将数字指标转换为等效的模拟滤波器指标 设计对应的模拟…

马克思主义哲学知识梳理(考公版)

马克思主义哲学是照亮我们认识世界、改造世界的明灯&#xff0c;考公人学好它&#xff0c;笔试面试都能 “开挂”。下面就一起来梳理这些重要内容。 一、哲学 哲学就像是一门 “智慧的学问”&#xff0c;它是对世界基本和普遍的问题研究的学科&#xff0c;探索着宇宙、人生、…

Java设计模式:行为型模式→状态模式

Java 状态模式详解 1. 定义 状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在内部状态改变时改变其行为。状态模式通过将状态需要的行为封装在不同的状态类中&#xff0c;实现对象行为的动态改变。该模式的核心思想是分离不同状态…

游戏引擎 Unity - Unity 下载与安装

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

Vue指令v-on

目录 一、Vue中的v-on指令是什么&#xff1f;二、v-on指令的简写三、v-on指令的使用 一、Vue中的v-on指令是什么&#xff1f; v-on指令的作用是&#xff1a;为元素绑定事件。 二、v-on指令的简写 “v-on&#xff1a;“指令可以简写为”” 三、v-on指令的使用 1、v-on指令绑…

C++游戏开发实战:从引擎架构到物理碰撞

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 C 是游戏开发中最受欢迎的编程语言之一&#xff0c;因其高性能、低延迟和强大的底层控制能力&#xff0c;被广泛用于游戏…

【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;贪心算法篇–CSDN博客 文章目录 前言例题1.买卖股票的最佳时机2.买卖股票的最佳时机23.k次取…

unity学习25:用 transform 进行旋转和移动,简单的太阳地球月亮模型,以及父子级关系

目录 备注内容 1游戏物体的父子级关系 1.1 父子物体 1.2 坐标关系 1.3 父子物体实际是用 每个gameobject的tranform来关联的 2 获取gameObject的静态数据 2.1 具体命令 2.2 具体代码 2.3 输出结果 3 获取gameObject 的方向 3.1 游戏里默认的3个方向 3.2 获取方向代…

虚幻基础17:动画层接口

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 animation layer interface animation layer interface 动画层接口&#xff1a;动画图表的集。仅有名字。 添加到动画蓝图中&#xff0c;由动画蓝图实现动画图表。