今天早高峰在地铁上突然有一个疑惑:String 是immutable是为了保证线程安全,Integer也是Immutable,为什么并发的时候建议使用AtomicInteger呢?
晚上回来查阅相关资料得出总结:
String a="test";
String b="test";
System.out.println(a==b);
System.out.println(System.idntityHashCode(a));
System.out.println(System.identityHashCode(b));
输出:true
851664923
851664923
//为什么有觉得可变呢?
String a="test";
a="test1"
a就变成了test1,其实在这里是新建了一个"test1"字符串对象(如果常量池没有这个值的话就是新建)。然后将变量引用指向它。注意:这里并没有修改"test"这个变量的内部状态,"test"这个字符串对象是线程安全的。
除非你用final修饰,否则所有的变量指向都是可变的。
这种情况下要保证线程安全性:
- 可以考虑使用volatile确保可见性。
- 可以使用final修饰
- 你可以使用AtomicReference之类的原子对象,对于Integer等也有AtomicInteger之类的
- 对相应代码区域加锁
有兴趣可以查看这两篇文章:
String是线程安全的吗?那String岂不是不能进行同步?
Java多线程系列--“JUC原子类”04之 AtomicReference原子类
综上:String Immutable为了线程安全知识相对的(字符串常量值不可变),但是引用可变,所以为了并发的时候线程安全,可以使用上面所说的几种方案。(如果有更好的认识深度,欢迎讨论)有兴趣可以查看我之前写的一篇文章关于介绍:String为什么是final修饰的
问题:
- int和Integer有什么区别?谈谈Integer的值缓存范围?
知识点
- Integer缓存或者String 常量池缓存用到的设计模式-享元模式。
相关代码(好记性不如烂笔头,代码是最好的理解):
package yonghui.cn.firstthread.flyweight;
/**
* 作者:huangchen on 2018/7/26 20:57
* 邮箱:huangchen@yonghui.cn
*/
public interface IBike {
void biliing(int time);
}
package yonghui.cn.firstthread.flyweight;
/**
* 作者:huangchen on 2018/7/26 20:58
* 邮箱:huangchen@yonghui.cn
*/
public class ShareBike implements IBike {
private int price;//单价
private int total;//总价
@Override
public void biliing(int time) {
System.out.println("total price is" + price * time);
}
}
package yonghui.cn.firstthread.flyweight;
import java.util.HashMap;
/**
* 作者:huangchen on 2018/7/26 20:11
* 邮箱:huangchen@yonghui.cn
*/
public class FlyWeightFactory {
private HashMap<String, IBike> map = new HashMap<>();
public IBike getIBike(String name) {
IBike iBike;
if (map.containsKey(name)) {
System.out.println("押金已经交过了" + name);
iBike = map.get(name);
return iBike;
} else {
System.out.println("押金没有交,开始交押金299元");
iBike = new ShareBike();
map.put(name, iBike);
return iBike;
}
}
}
package yonghui.cn.firstthread.flyweight;
/**
* 作者:huangchen on 2018/7/26 20:16
* 邮箱:huangchen@yonghui.cn
*/
public class Client {
public void test(){
FlyWeightFactory flyWeightFactory = new FlyWeightFactory();
IBike ofo = flyWeightFactory.getIBike("ofo");
ofo.biliing(2);
IBike mobike = flyWeightFactory.getIBike("mobike");
mobike.biliing(1);
IBike ofo1 = flyWeightFactory.getIBike("ofo");
ofo1.biliing(3);
}
}
关于享元模式有兴趣可以参考:Android的设计模式-享元模式。
- 自动装箱、自动拆箱发生在编译阶段。静态工厂方法valueof()使用了缓存机制,自动装箱的时候,缓存机制起作用。实际开发中,避免无意的装箱、拆箱行为(不管是内存使用还是运行速度、10w个Java对象比10w整数的开销要大得多,光是对象头空间占用已经是数量级的差距了)。
- 对象的内存结构:对象由对象头、对象实例、对齐填充三部分组成。具体有兴趣可以参考:Java对象内存布局
回答问题:
int是我们常说的整形,是八大基本数据类型之一,占4个字节,取值范围2的31次方减去1,Java需要号称一切都是对象,但是基本数据类型是个例外。
Integer是int对应的包装类,他有一个int类型存字段(private final修饰,Immutable),并且提供了基本操作,比如数字运算、int和字符串之间的转换。在Java5中,引入了自动装箱、拆箱功能。Java根据上下文,自动进行转换,极大简化了相关编程。
关于Integer的值缓存,这涉及Java5的内一个改进。大部分数据操作都集中在有限的、较小的数值范围,因而,在Java 5 中新增了静态工厂方法valueof,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照Javadoc,这个值默认缓存-128-127之间。
//Integer部分源码
//Immutable private final
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
参考:
- String是线程安全的吗?那String岂不是不能进行同步?
- Java多线程系列--“JUC原子类”04之 AtomicReference原子类
- String为什么是final修饰的
- Android的设计模式-享元模式。
- Java对象内存布局
- Integer部分源码
- 极客时间APP核心技术第七讲|int和Integer有什么区别?
- 自己写的Demo中部分代码
声明:此为原创,转载请联系作者
作者:微信公众号添加公众号-遛狗的程序员 ,或者可以扫描以下二维码关注相关技术文章。
qrcode_for_gh_1ba0785324d6_430.jpg当然喜爱技术,乐于分享的你也可以可以添加作者微信号:
WXCD.jpeg
网友评论