一、不要在构造过程当中使this引用逸出。当且仅当对象的构造函数返回时,对象才处于可预测和一致的状态,当从对象的构造函数中发布对象时,只是发布了一个还没有构造完成的对象。只有当构造函数返回时,this引用才应该从线程中逸出,构造函数能够将this引用保存到某个地方,只要其余线程不会在构造函数以前使用它。若是想在构造函数中注册事件监听器或者启动线程,能够使用一个私有的构造函数和公共的工厂方法。缓存
public class SafeListener { private final EventListener listener; private SafeListener(){ listener = new EventListener(){ public void onEvent(Event e){ //TODO } }; } public static SafeListener newInstance(EventSource source){ SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe; } }
二、线程封闭(Thread Confinement),JDBC中的Connection对象就使用了线程封闭技术。JDBC规范并不要求Connection是线程安全的,可是链接池将其分配给一个线程以后,到Connection返回给链接池以前,链接池不会再把该Connection分配给其余线程使用,所以至关于线程封闭了;ThreadLocal也是线程封闭的。 AD HOC线程封闭,不多用(未懂是什么)。 栈封闭:只能经过局部变量才能访问对象(局部变量被封闭在执行线程中,所以天然的封闭了)。书中的例子:安全
public int loadTheArk(Collection<Animal> candidates){ SortedSet<Animal> animals; int numPairs = 0; Animal candidate = 0; //animals封闭在方法中,不要使其逸出 animals = new TreeSet<Animal>(new SpecialGenderComparator()); animals.addAll(candidates); for(Animal a : animals){ if(candidate == null || !candidate.isPotentialMate(a)) candidate = a; else{ ark.load(new AnimalPair(candidate,a)); ++numPairs; candidate = null; } } return numPairs; }
线程封闭性更规范的方法:ThreadLocal,防止可变的单实例变量(Singleton)或全局变量进行共享。框架
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>(){ public Connection initialValue(){ Connection conn = null; try { conn = DriverManager.getConnection("URL"); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } }; public static Connection getConnection(){ return connectionHolder.get(); }
能够用来保存事务上下文,避免调用每一个方法时都要传递执行上下文信息。这样也会使运用了该机制的框架代码与通常代码耦合在一块儿。滥用ThreadLocal相似于全局变量,下降代码可重用性,并在类之间引入隐含的耦合性。函数
三、不变性:不可变对象必定是线程安全的,全部的域都是final类型的,对象也未必是不可变的,由于final类型的域能够保存可变对象的引用。符合如下条件则不可变: .)对象建立之后其状态就不能修改; .)对象的全部域都是final类型; .)对象都是正确建立的(在对象建立期间,this引用没有逸出)。 “不可变的对象”与“不可变的对象引用”之间存在差别,保存在不可变对象中的程序状态依然能够更新,可经过一个保存新状态的实例来替换原有的不可变对象。 大神们说的良好变成习惯:除非须要更高的可见性,不然将全部的域都声明为私有域;除非须要某个域是可变的,不然应将其声明为final域。 能够使用指向不可变容器对象的volatile类型引用以缓存最新的结果。this
4安全发布:安全发布一个对象,对象引用和对象状态必须同时对其余线程可见,一个正确构造的对象能够经过如下方式安全发布: .)在静态初始化函数中初始化一个对象引用; .)将对象的引用保存到volatile类型的域或者AtomicReferance对象中; .)将对象的引用保存到某个正确构造对象的final类型域中。 .)将对象的引用保存到一个由锁保护的域中。线程