我是靠谱客的博主 魁梧钢笔,最近开发中收集的这篇文章主要介绍多线程之享元模式和final原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

多线程之享元模式和final原理

    • 1 享元模式
      • 1 定义
      • 2 体现
        • 1 包装类
        • 2 BigDecimal类
    • 2 final原理
      • 1 设置final的原理
      • 2 获取final的原理
    • 3 无状态

1 享元模式

1 定义

享元模式,Flyweight pattern, 当需要重用数量有限的同一类对象时使用.

2 体现

1 包装类

Jdk中Boolean, Byte, Short, Integer, Long, Character等包装类提供了valueOf方法.以Long的valueOf为例, 会缓存-128到127之间的Long对象,在此区间会重用对象,大于这个范围才会新建Long对象.

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

Byte,Short, Long缓存的范围都是-128到127

Character缓存的范围是0-127

Integer的默认范围是-128到127, 最小值不能变,最大值可以通过调整虚拟机参数-Djava.lang.Integer.IntegerCache.high来改变

Boolean缓存了TRUE和FALSE

2 BigDecimal类
    private static BigDecimal add(BigInteger fst, int scale1, BigInteger snd, int scale2) {
        int rscale = scale1;
        long sdiff = (long)rscale - scale2;
        if (sdiff != 0) {
            if (sdiff < 0) {
                int raise = checkScale(fst,-sdiff);
                rscale = scale2;
                fst = bigMultiplyPowerTen(fst,raise);
            } else {
                int raise = checkScale(snd,sdiff);
                snd = bigMultiplyPowerTen(snd,raise);
            }
        }
        BigInteger sum = fst.add(snd);
        return (fst.signum == snd.signum) ?
                new BigDecimal(sum, INFLATED, rscale, 0) :
                valueOf(sum, rscale, 0);
    }

单个方法是采用保护性拷贝类方式, 是原子的,线程安全的, 但是不能保证多个方法的组合是原子的,线程安全的,所以在使用中,需要其他方法保证,如使用AtomicReference.

2 final原理

1 设置final的原理

根据之前volatile原理,对比final的实现.

public class TestFinal {
 final int a = 20;
}

对应字节码文件:

0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 20
7: putfield #2 // Field a:I
 <-- 添加了写屏障
10: return

发现 final 变量的赋值也会通过 putfield 指令来完成,同样在这条指令之后也会加入写屏障,保证在其它线程读到 它的值时不会出现为 0 的情况

2 获取final的原理

public class TestFinal {
 final int A = 20;
 final int B = Short.MAX_VALUE + 1;
    
 static final int a = 20;
 static final int b = Short.MAX_VALUE + 1; 
}

根据编译的字节码文件可知, 当数据较小就在栈内存中获取,数据量超过最大,就在类常量池中.

3 无状态

在 web 中,设计 Servlet 时为了保证其线程安全,都会有这样的建议,不要为 Servlet 设置成员变量,这种没有任何成员变量的类是线程安全的

因为成员变量保存的数据也可以称为状态信息,因此没有成员变量就称之为【无状态】

最后

以上就是魁梧钢笔为你收集整理的多线程之享元模式和final原理的全部内容,希望文章能够帮你解决多线程之享元模式和final原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部