ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式Copy-on-write

2021-06-03 18:32:58  阅读:224  来源: 互联网

标签:iface String public write 进程 Router 设计模式 Copy 路由表


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);
  }
}

标签:iface,String,public,write,进程,Router,设计模式,Copy,路由表
来源: https://www.cnblogs.com/PythonOrg/p/14846428.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有