并发编程(九)

92 篇文章 0 订阅
10 篇文章 0 订阅

共享模型之不可变

可变和不可变类的使用例子

  • SimpleDateFormat日期格式化类, 由于是线程不安全的, 所以多线程调用时, 会时不时的抛异常

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    System.out.println(sdf.parse("2021-05-21"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

		# 以上例子可以通过加同步锁来解决, 但这样会`影响并发性能`
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                synchronized (sdf) {
                    try {
                        System.out.println(sdf.parse("2021-05-21"));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
  • 可以通过防止修改对象内部属性(状态不可变), 来实现线程安全. 由于不能修改, 所以不存在线程不安全问题
  • Java8开始提供 DateTimeFormatter类, 代替 SimpleDateFormat类

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                LocalDate date = dtf.parse("2021-05-21", LocalDate::from);
                System.out.println(date);
            }).start();
        }

不可变设计: 保护性拷贝(Defensive Copy)

  • 以 String类为例
  1. String类用 final修饰, 防止了继承及方法被覆盖后引起不可变性被破坏
  2. 类中所有属性都用 final修饰, 来保证是只读的
  3. 类中修改值相关的方法的内部实现, 起始为复制副本同时创建新的
  4. 类构造& 修改值相关的方法内部实现, 实际上返回的是新创建的 String对象.这种通过创建副本来规避共享的手段称为保护性拷贝
  • final原理
    与 volatile相同, 当一个变量修饰为 final, 则会在字节码成面加写屏障, 来保证在其它线程读值时的可见性

无状态类设计

  • 没有任何成员变量的类是线程安全的, 因为成员变量保存的数据也可以称为状态信息. 因此没有成员变量又称为无状态

享元模式(Flyweight Pattern), 归类 Structual Patterns

  • Boolean, Byte, Short, Integer, Long, Character等包装类的 valueOf方法会缓存 如: -128~127范围内的对象, 然后使用时会重用此范围内的对象, 不在范围内的, 才会新建
    *Byte, Short, Integer, Long的缓存范围都是 -128~127
    *Character的缓存范围是 0~127
    *Boolean缓存了 TRUE和 FALSE
    *Integer的最小值不能变, 但最大值可以通过调整虚拟机参数 -Djava.lang.Integer.IntegerCache.high来变更

	public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }

如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值