Immutable模式可以说是多线程设计模式中最为简单的模式,简单到可以不用考虑多线程带来的影响。话不多说,先上代码:
public final class Person{
private final String name;
private final String address;
public Person(String name, String address){
this.name = name;
this.address = address;
}
public String getName(){
return this.name;
}
public String getAddress(){
return this.address;
}
@override
public String toString(){
return "[ Person: name = " + name + ", address = " + address + " ]";
}
}
public class PrintPersonThread extends Thread{
private Person person;
public PrintPersonThread(Person person){
this.person = person;
}
@override
public void run(){
while(true){
System.out.println(Thread.currentThread().getName() + " prints" + person);
}
}
}
public class Main{
Person alice = new Person("Alice", "Alaska");
new PrintPersonThread(alice).start();
new PrintPersonThread(alice).start();
new PrintPersonThread(alice).start();
}
由于共享的资源对象alice没有setter函数修改成员变量,同时String类型是不可变的,因此alice对象一旦创建,成员变量的值也不会改变,多个线程同时访问时也不会造成数据不一致性。Immutable的意思即为“不变”的意思。类图如下:
以上就是Immutable模式的内容,是不是超级简单~~简单来说就是对象的状态在初始化之后根本不会改变,也就不必担心多线程对其进行修改了。
需要注意的是,并非将变量修饰为private,同时没有getter函数就可以保证对象是线程安全的,如下所示:
class Test
{
public static void main (String[] args)
{
Info info = new Info(new StringBuilder("tom"));
StringBuilder copy = info.getName();
copy.replace(0,1,"aa");
System.out.println(info.getName());
}
}
class Info{
private final StringBuilder name;
public Info(StringBuilder name){
this.name = name;
}
public StringBuilder getName(){
return this.name;
}
}
Info类中的变量name声明为private以及final。虽然final保证了name只能被赋值一次,但是由于StringBuilder是可变对象,Info中的name属性仍是非线程安全的。上述代码最终输出"aaom",因此Info中name字段在初始化之后仍被修改了。
由于main方法的copy变量和Info中name变量指向的是同一内存地址,因此copy指向地址中存储的值改变了,Info中name指向的地址中的值也就变化了。
所以,我们必须小心确认资源对象中的值不会被改变,才能使用Immutable模式进行程序设计。好啦,关于Immutable就介绍到这里,下一章节我们将介绍Guarded Suspension模式,欢迎大家继续阅读。