定义:
immutable模式存在着确保实例状态不发生改变的类。在访问这些事例时不需要执行互斥的处理。
引例:
这是一个使用了immutable模式的小例子。
名字 | 说明 |
person | 人的类 |
main | 测试行为类 |
printpersonthread | 显示person示例的线程类 |
/* *
* 1.final class Person ,final斌不是Person一定的,Person不能被继承,防止被修改。
* 2.字段没有set方法,所以不能被改变
* */
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 name;
}
public String getAddress() {
return address;
}
public String toString() {
return "[ Person: name = " + name + ", address = " + address + " ]";
}
}
public class PrintPersonThread extends Thread {
private Person person;
public PrintPersonThread(Person person) {
this.person = person;
}
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " prints " + person);
}
}
}
public class Main {
public static void main(String[] args) {
Person alice = new Person("Alice", "Alaska");
new PrintPersonThread(alice).start();
new PrintPersonThread(alice).start();
new PrintPersonThread(alice).start();
}
}
结果:
Thread-5 prints [ Person: name = Alice, address = Alaska ]
Thread-5 prints [ Person: name = Alice, address = Alaska ]
Thread-5 prints [ Person: name = Alice, address = Alaska ]
Thread-5 prints [ Person: name = Alice, address = Alaska ]
Thread-5 prints [ Person: name = Alice, address = Alaska ]
immutable模式中的角色
immutable角色是一个类,在这个类中字段是不能被修改的,也不存在修改的方法。immutable角色的实例一旦被创建,状态就不再改变,无需做互斥处理。
tips: java中final含义:
final类无法扩展,没有子类。final方法在子类中不能被重写。final的字段不能多次赋值。
何时使用
实例创建后状态不发生变化时。实例是共享的,且被经常访问。
零碎的知识点:
arraylist类是线程不安全的。copyonwritearraylist和collections.synchronizedlist是安全的。
性能测试题:
在Single Threaded Execution模式中我们使用synchronized保证线程安全的,有些时候可以用immutable保证线程的安全。我么做一个性能的测试。
/*测试同步与非同步的区别*/
public class Main {
private static final long CALL_COUNT = 10000000L;
public static void main(String[] args) {
trial("NotSynch", CALL_COUNT, new NotSynch());
trial("Synch", CALL_COUNT, new Synch());
}
private static void trial(String msg, long count, Object obj) {
System.out.println(msg + ": BEGIN");
long start_time = System.currentTimeMillis();
for (long i = 0; i < count; i++) {
obj.toString();
}
System.out.println(msg + ": END");
System.out.println("Elapsed time = " + (System.currentTimeMillis() - start_time) + "msec.");
}
}
class NotSynch {
private final String name = "NotSynch";
public String toString() {
return "[ " + name + "]";
}
}
class Synch {
private final String name = "Synch";
public synchronized String toString() {
return "[ " + name + "]";
}
}
NotSynch: BEGIN
NotSynch: END
Elapsed time = 114msec.
Synch: BEGIN
Synch: END
Elapsed time = 1595msec.
从这个测试我们看出。两者的性能差的还是挺大。
思考题:
明明没有setter方法,却不是immutable类
public final class UserInfo {
private final StringBuffer info;
public UserInfo(String name, String address) {
this.info = new StringBuffer("<info name=\"" + name + "\" address=\"" + address + "\" />");
}
public StringBuffer getInfo() {
// 外部也可以改变info的值
return info;
}
public String toString() {
return "[ UserInfo: " + info + " ]";
}
}
public class Main {
public static void main(String[] args) {
// 制作实体
UserInfo userinfo = new UserInfo("Alice", "Alaska");
// 显示
System.out.println("userinfo = " + userinfo);
// 状态变更
StringBuffer info = userinfo.getInfo();
info.replace(12, 17, "Bobby"); // "Alice"竚琌12..16
// 再度显示
System.out.println("userinfo = " + userinfo);
}
}
结果大家自己试一试。
判断是不是immutable类?
public final class ImmutablePerson {
private final String name;
private final String address;
public ImmutablePerson(String name, String address) {
this.name = name;
this.address = address;
}
public ImmutablePerson(MutablePerson person) {
//person可能会变
this.name = person.getName();
this.address = person.getAddress();
}
public MutablePerson getMutablePerson() {
/* 通过this构造,保证了数据一致 */
return new MutablePerson(this);
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public String toString() {
return "[ ImmutablePerson: " + name + ", " + address + " ]";
}
}
如何更改?
public final class ImmutablePerson {
private final String name;
private final String address;
public ImmutablePerson(String name, String address) {
this.name = name;
this.address = address;
}
// 不可变
public ImmutablePerson(MutablePerson person) {
synchronized (person) {
this.name = person.getName();
this.address = person.getAddress();
}
}
public MutablePerson getMutablePerson() {
return new MutablePerson(this);
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public String toString() {
return "[ ImmutablePerson: " + name + ", " + address + " ]";
}
}
具体的原理自己体会!so easy 对不。