1.Copy-on-Write

又称COW,写时复制

String的replace()方法,没有修改内部的value数组,而是新创建了一个不可变对象

这种方法在解决不可变对象时,经常使用

这其实就是一种Copy-on-write方式

不可变对象的写操作往往都是使用 Copy-on-Write 方法解决的,当然 Copy-on-Write 的应用领域并不局限于 Immutability 模式

2.CopyOnWriteArrayList 和 CopyOnWriteArraySet

本质就是使用了COW思想

线程安全,试用于读多写少的场景,提升了性能的同时,也是通过COW复制出新的内存空间的代价换来的

读无锁,性能高。

修改的时候,会同事复制整个容器,以复制内存为代价,提升性能

3.linux的copy-on-write

fork子进程的时候,也是使用这种思路

父进程的地址空间现在用到了 1G 的内存,那么 fork() 子进程的时候要复制父进程整个进程的地址空间(占有 1G 内存)给子进程,这个过程是很耗时的。而 Linux 中的 fork() 函数就聪明得多了,fork() 子进程的时候,并不复制整个进程的地址空间,而是让父子进程共享同一个地址空间;只用在父进程或者子进程需要写入的时候才会复制地址空间,从而使父子进程拥有各自的地址空间。

在进程方面,因为子进程和父进程必须是不同的进程地址空间,数据也要隔离,所以copy-on-write其实只是一种延迟策略,在需要时复制,不需要时使用父进程的地址空间

4.微服务路由表应用案例

客户端调用远程服务,需要获取路由表,然后从路由表选则其中之一去调用

每次调用前,都需要获取路由表,服务的上下线状态不是很频繁,而且一段时间间隔非实时性也是可以容忍的,弱一致性

思考:

服务提供方,每次上线,下线,都会更新路由信息。

是否可以通过更新Router的一个状态位来表示,如果这样,那么客户端获取路由,访问该状态位的时候都需要同步访问(有可能获取状态的时候,状态正在被修改,假如被加锁,这时候就需要等待,等待写完了,再读),性能不好。如果采用Immutability不可变模式,每次上线,下线,都创建新的Router对象或者删除对应的Router对象,直接访问不受影响

代码范例


//路由信息
public final class Router{
private final String ip;
private final Integer port;
private final String iface;
//构造函数
public Router(String ip,
Integer port, String iface){
this.ip = ip;
this.port = port;
this.iface = iface;
}
//重写equals方法
public boolean equals(Object obj){
if (obj instanceof Router) {
Router r = (Router)obj;
return iface.equals(r.iface) &&
ip.equals(r.ip) &&
port.equals(r.port);
}
return false;
}
public int hashCode() {
//省略hashCode相关代码
}
}
//路由表信息
public class RouterTable {
//Key:接口名
//Value:路由集合
ConcurrentHashMap<String, CopyOnWriteArraySet<Router>>
rt = new ConcurrentHashMap<>();
//根据接口名获取路由表
public Set<Router> get(String iface){
return rt.get(iface);
}
//删除路由
public void remove(Router router) {
Set<Router> set=rt.get(router.iface);
if (set != null) {
set.remove(router);
}
}
//增加路由
public void add(Router router) {
Set<Router> set = rt.computeIfAbsent(
route.iface, r ->
new CopyOnWriteArraySet<>());
set.add(router);
}
}

设计模式Copy-on-write的更多相关文章

  1. HEC-ResSim原文档

              HEC-ResSim Reservoir System Simulation             User's Manual       Version 3.1 May 201 ...

  2. PHP设计模式(六)原型模式(Prototype For PHP)

    原型设计模式: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型设计模式简单的来说,顾名思义, 不去创建新的对象进而保留原型的一种设计模式. 缺点:原型设计模式是的最主要的缺点就 ...

  3. C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝

    原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...

  4. C#设计模式

    自从上次记录完“重构之道”以后,查询设计模式挺麻烦的.就打算把原先写的设计模式系列合并一下. 设计原则 使用设计模式的根本原因就是适应需求变化,提高代码的复用率,使程序更具有扩展性和可维护性. SOL ...

  5. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  6. 小菜学习设计模式(四)—原型(Prototype)模式

    前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...

  7. Net设计模式实例之原型模式( Prototype Pattern)

    一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...

  8. 你真的了解iOS代理设计模式吗?

    在项目中我们经常会用到代理的设计模式,这是iOS中一种消息传递的方式,也可以通过这种方式来传递一些参数.这篇文章会涵盖代理的使用技巧和原理,以及代理的内存管理等方面的知识.我会通过这些方面的知识,带大 ...

  9. 设计模式之美:Iterator(迭代器)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Iterator 模式结构样式代码. 实现方式(二):实现 IEnumerable 中序遍历二叉树. 实现方式(三):实现 Bi ...

  10. 浅谈 MVVM 设计模式在 Unity3D 中的设计与实施

    初识 MVVM 谈起 MVVM 设计模式,可能第一映像你会想到 WPF/Sliverlight,他们提供了的数据绑定(Data Binding),命令(Command)等功能,这让 MVVM 模式得到 ...

随机推荐

  1. 1075 PAT Judge

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...

  2. c协程库libco几点体会

    https://www.cnblogs.com/dearplain/p/9820913.html 这里说的是Tencent开源的libco. libco的用途和依赖 主要还是c/c++服务端,相比li ...

  3. 05- 移动端APP的分类 与对比webApp hybridApp nativeApp

    随着智能手机的普及,移动端应用几乎成为每个互联网产品的标配.在快速迭代的互联网战场中高效开发.低成本上线产品,是每个应用开发团队追求的目标.此时,选择合适的应用类型和开发模式便至关重要.移动应用可以粗 ...

  4. Windows API初练手 -- 疯狂写文件代码

    警告:恶作剧软件,慎用!仅供初学者研究代码所用!!! 提示:默认文件创建目录在"D:\test",如果需要使用的话请自行更改目录. 1. Windows API 版本 (调用系统函 ...

  5. UVA11292杀怪

    题意:      一个怪物有N个头,每个头都有半径,然后有M个骑士,每个骑士能砍掉半径小于等于 X[i]的头,花费为X[i],并且一个骑士只能用一次,问砍掉怪物所有头的最小花费. 思路:       ...

  6. Caddy-基于go的微型serve用来做反向代理和Gateway

    1.简单配置 2.go实现,直接一个二进制包,没依赖. 3.默认全站https 常用 反向代理,封装多端口gateway 使用:启动直接执行二进制文件 caddy 就行 根据输出信息 直接https: ...

  7. javaScript的成长之路【何为函数,面向对象又是啥!!!】

  8. 使用jenkins一键打包发布vue项目

    jenkins的安装 Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建.测试和部署软件. Jenkins 支持各种运行方式,可通过系统包.Docker 或者通过一个独立 ...

  9. QQ可以登录,网页无法访问

    之前以为是网络的问题,但是,后来发现QQ却可以登录,这是第二次碰到这个情况,所以总结一下 一般我们电脑上都会安装一个杀毒软件,比如火绒等等.我电脑上用的联想自带的电脑管家 我们可以在工具箱中找到网络诊 ...

  10. 一种用于 API 的查询语言-GraphQL

    GitHub地址 官网地址 中文网址