}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
线程封闭
主要的线程封闭技术有:栈封闭和ThreadLocal类
栈封闭:把变量都声明为局部变量,并且不要使它们逸出
ThreadLocal类:这是维持线程封闭性更规范的一种方法,ThreadLocal对象通常用于防止对可变的单实例变量或全局变量进行共享。使用方法如下代码:
[java]
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionDispenser {
static String DB_URL = "jdbc:mysql://localhost/mydatabase";
private ThreadLocal
= new ThreadLocal
public Connection initialValue() {
try {
return DriverManager.getConnection(DB_URL);
} catch (SQLException e) {
throw new RuntimeException("Unable to acquire Connection, e");
}
};
};
public Connection getConnection() {
return connectionHolder.get();//当某个线程初次调用ThreadLocal.get方法时,就会调用initialValue来获取初始值。
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionDispenser {
static String DB_URL = "jdbc:mysql://localhost/mydatabase";
private ThreadLocal
= new ThreadLocal
public Connection initialValue() {
try {
return DriverManager.getConnection(DB_URL);
} catch (SQLException e) {
throw new RuntimeException("Unable to acquire Connection, e");
}
};
};
public Connection getConnection() {
return connectionHolder.get();//当某个线程初次调用ThreadLocal.get方法时,就会调用initialValue来获取初始值。
}
}
当某个频繁执行的操作需要一个临时对象,例如一个缓冲区,而同时又希望避免在每次执行时都重新分配该临时对象,就可以使用这项技术
开发人员经常滥用ThreadLocal,例如将所有全局变量都作为ThreadLocal对象,或者作为一种“隐藏”方法参数的手段。ThreadLocal变量类似于全局变量,它能降低代码的可重用性,并在类之间引入隐含的耦合性,因此在使用时要格外小心
不变性
不可变对象一定是线程安全的
当满足以下所有条件时,对象才是不可变的
(1)对象创建以后其状态就不能修改
(2)对象的所有域都是final类型
(3)对象是正确创建的(在对象的创建期间,this引用没有逸出)
一个编程过程中的良好习惯
正如“除非需要更高的可见性,否则应将所有的域都声明为私有域”是一个良好的编程习惯,“除非需要某个域是可变的,否则应将其声明为final域”也是一个良好的编程习惯
安全的发布
上面讨论的都是如何确保对象不被发布,现在开始讨论如何安全的发布
安全发布的常用模式:
要安全地发布一个对象,对象的引用以及对象的状态必须同时对其他线程可见。一个正确构造的对象可以通过以下方式来安全地发布
(1)在静态初始化函数中初始化一个对象的引用
(2)将对象的引用保存到volatile类型的域或者AtomicReferance对象中
(3)将对象的引用保存到某个正确构造对象的final类型域中
(4)将对象的引用保存到一个由锁保护的域中(如将对象放入Vector或synchronizedList容器)