zoukankan      html  css  js  c++  java
  • 第三部分-并发设计模式28:Immutability

    1.什么是Immutability

    Immutability,不变性,
    叫做不变性设计模式,简单来说就是对象一旦创建,状态就不再发生变化。
    变量一旦被赋值,就不允许修改了(没有写操作);没有修改操作,就保持了不变性

    2.什么情况用Immutablity设计模式

    多个线程同时读写同一个共享变量存在并发问题,核心条件是读写,如果只有读,没有写,是没有并发问题的
    解决并发问题,最简单的办法就是让共享变量只有读操作,没有写操作。

    3.快速实现具备不可变的类

    将一个雷的所有属性都设置为final,并且只允许存在只读方法,那么这个类基本上就具备不可变性了。并且这个类本身也是final的,这个类本身不允许继承。

    4.jdk中使用Immutablity设计模式的,不可变的类

    Long,String

    
    public final class String {
      private final char value[];
      // 字符替换
      String replace(char oldChar, 
          char newChar) {
        //无需替换,直接返回this  
        if (oldChar == newChar){
          return this;
        }
    
        int len = value.length;
        int i = -1;
        /* avoid getfield opcode */
        char[] val = value; 
        //定位到需要替换的字符位置
        while (++i < len) {
          if (val[i] == oldChar) {
            break;
          }
        }
        //未找到oldChar,无需替换
        if (i >= len) {
          return this;
        } 
        //创建一个buf[],这是关键
        //用来保存替换后的字符串
        char buf[] = new char[len];
        for (int j = 0; j < i; j++) {
          buf[j] = val[j];
        }
        while (i < len) {
          char c = val[i];
          buf[i] = (c == oldChar) ? 
            newChar : c;
          i++;
        }
        //创建一个新的字符串返回
        //原字符串不会发生任何变化
        return new String(buf, true);
      }
    }
    

    String中的可变方法,往往是新new 出一个新不可变对象来实现,会不会浪费内存呢?会的

    5.如何解决内存浪费,使用享元模式

    Long,Integer,Short,Byte 等这些基本数据类型的包装类都使用了享元模式

    Long使用享元模式的范例(本质上是一个对象池或者缓存池的概念)

    
    Long valueOf(long l) {
      final int offset = 128;
      // [-128,127]直接的数字做了缓存
      if (l >= -128 && l <= 127) { 
        return LongCache
          .cache[(int)l + offset];
      }
      return new Long(l);
    }
    //缓存,等价于对象池
    //仅缓存[-128,127]直接的数字
    static class LongCache {
      static final Long cache[] 
        = new Long[-(-128) + 127 + 1];
    
      static {
        for(int i=0; i<cache.length; i++)
          cache[i] = new Long(i-128);
      }
    }
    

    String,Integer类也是类似

    6.使用享元模式的这些包装类为什么不适合用于锁?

    是因为有些看起来像是私有的锁,其实是共有的

    伪代码,看着像是两把锁,其实是同一把锁

    
    class A {
      Long al=Long.valueOf(1);
      public void setAX(){
        synchronized (al) {
          //省略代码无数
        }
      }
    }
    class B {
      Long bl=Long.valueOf(1);
      public void setBY(){
        synchronized (bl) {
          //省略代码无数
        }
      }
    }
    

    7.Immutability模式注意事项

    • 对象的所有属性都是final的,并不能保证不可变性
    • 不可变对象也需要正确发布
      final修饰的普通对象,对象属性是可以被修改的

    8.正确使用Immutability的姿势

    public final class ServerConfig {
    
        private final int masterExecThreads = 100;
        private final int masterExecTaskNum = 20;
        private final int listenPort = 5678;
        private final String address = NetUtils.getAddr(listenPort);
    
        public String getAddress() {
            return address;
        }
    
        public int getMasterExecThreads() {
            return masterExecThreads;
        }
    
        public int getMasterExecTaskNum() {
            return masterExecTaskNum;
        }
    
        public int getListenPort() {
            return listenPort;
        }
    }
    
    原创:做时间的朋友
  • 相关阅读:
    7_布局管理器.md
    5_资源文件.md
    css tabbar添加激活样式,竖条
    云代码仓库,git使用
    express配置跨域
    跨域无法携带cookie,samesite警告
    Syntax Error: TypeError: Cannot read property 'parseComponent' of undefined
    django使用uwsgi启动
    linux下安装配置python3.6、虚拟环境
    linux下virtualenvwrapper、python虚拟环境命令操作
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/14838096.html
Copyright © 2011-2022 走看看