本文作者:王一飞,叩丁狼高级讲师。原创文章,转载请注明出处。
接上篇,本篇讲解线程另外一个设计模式:Immutable Pattern. 不可变模式.
概念
Immutable Pattern:不可变模式, 设计思路非常简单, 要求共享资源是一个不可改变对象, 线程只能访问资源,而不允许对资源修改.并发环境下即使不使用加锁操作,也可保证线程操作安全.
知识补充
敞开讲述前,先来科普一下不可对象:
java中类分2种类型, 可变类与不可变类, 不可变类是指当类实例化后, 就不允许修改对象的任何属性值.常见不可变类有: 基本类型包装类(Integer/Long等), 还有String也是不可变类.这些类都满足一下几个条件:
1:对象实例化后其值(状态)不能在修改
2:对象的所有字段都是不可变的(即使用final修饰)
3:对象是正确方式创建的
public final class Integer extends Number implements Comparable<Integer> {
@Native public static final int MIN_VALUE = 0x80000000;
@Native public static final int MAX_VALUE = 0x7fffffff;
private final int value;
....
}
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
}
那如何构建出不可变对象了, 一般遵循下面几点:
1:把所有属性定义为private final类型, 初始化后不允许再修改
2:不定义setter方法,如果设置也要设置private 不允许外界访问
3:只提供getter方法,只允许访问
4:在构造器中初始化所以属性
5:类定义为final,防止出现子类(如果有必要)
代码演示
@Getter
@ToString
public final class User {
private final String idNumber; //身份证号
private final String username; //名称
public User(String idNumber, String username){
this.idNumber = idNumber;
this.username = username;
}
}
public class App {
public static void main(String[] args) {
final User user = new User("44080100000000", "wolfcode");
new Thread(new Runnable() {
public void run() {
System.out.println(user);
}
}).start();
new Thread(new Runnable() {
public void run() {
System.out.println(user);
}
}).start();
}
}
User(idNumber=44080100000000, username=wolfcode)
User(idNumber=44080100000000, username=wolfcode)
不管开启多少个线程, 打印的数据都是一样的.
运用
到这可能会发问:什么情况选择使用Immutable Pattern呢?建议满足下面2个条件时使用:
1:实例创建后状态不能改变
2:实例是共享的,且必须频繁访问
Immutable Pattern 的优势在不使用synchronized进行保护也可以满足线程安全性,当实例被共享,且被频繁访问时,Immutable 模式优点就体现出来了,相对synchronized来说,能极大提高性能。
所以在java的jdk标识类库中很多类都是用该模式:
包装类:Boolean Byte Character Double Float Integer Long Short Void
awt中的: Color
字符串: String
大数据类:BigInteger Bigdecimal
正则:Pattern
总结
Immutable Pattern:不可变模式, 就是将共享资源对象设计成不可变对象, 线程只可以获取,不可以修改.这便可实现线程安全目的.
网友评论