复习单例模式
?基本的单例模式:
?
public class SingletonTest{private static SingletonTestinstance;private SingletonTest() {}public static SingletonTest getInstance() {if (instance == null) {instance = new SingletonTest();}return instance;}}
?调用
public class Main {public static void main(String[] args) {SingletonTest singlonTest=SingletonTest.getInstance();}
?但是 这样在多线程模式下可能出现多实例的现象,模拟一下
public class Main {??static Set instanceSet =Collections.synchronizedSet(new HashSet());??public static void main(String[] args) {??long start = System.currentTimeMillis();?? Thread threads[] = new Thread[1000] ;??for (int i = 0; i < 1000; i++) {??threads[i] = new MyThread();
??}??for (int i = 0; i < 1000; i++) {???threads[i].start();?//??System.out.println(threads[i].getName());??}??long end = System.currentTimeMillis();??System.out.println("耗时:" + (end - start) + "ms");??System.out.println(instanceSet.size());??for(Iterator i=instanceSet.iterator();i.hasNext();){???System.out.println(i.next());??}?}}
class MyThread extends Thread {?public void run() {??SingletonTest a = SingletonTest.getInstance();
??Main.instanceSet.add(a);
?}}
?观察输出可以看到产生了多个实例。
防止这种多线程产生多实例的方法有:
1.方法前加 synchronized
public class SingletonTest{private static SingletonTest instance;private SingletonTest() {System.out.println("create instance");}public static synchronized SingletonTest getInstance() {if (instance == null) {instance = new SingletonTest();}return instance;}}
?这种效率较低 只能同时有一个线程调用getInstance?? 其实真正只要在? instance=new SingletonTest()同步。
?2.在产生实例的地方加同步
public class SingletonTest {private static SingletonTest instance = null;private SingletonTest() {System.out.println("create instance");}public static SingletonTest getInstance() {if(instance==null){ synchronized(SingletonTest.class){instance=new SingletonTest();}}return instance;}}
?这样处理有多线程时还是会产生多个实例
?
?3.双重锁
?
public class SingletonTest {private static SingletonTest instance = null;private SingletonTest() {System.out.println("create instance");}public static SingletonTest getInstance() {if(instance==null){synchronized(SingletonTest.class){if(instance==null){instance=new SingletonTest();}}}return instance;}}
?这也不是完美无缺的,在java的内存模型里有可能出现多个实例
instance = new Singleton();java代码的过程可解释如下 3个步骤?
?1??mem = allocate();? ?? ?? ?? ?//Allocate memory for Singleton object. % z$ S, _' s. D% A
2??instance = mem;? ?? ?? ?? ???//Note that instance is now non-null, but?
??????????????????????//has not been initialized. * X% ]1 @( c+ T4 H" ~, I
3??ctorSingleton(instance);? ?? ?//Invoke constructor for Singleton passing?instance. ! Z( m??
getInstance()
method.synchronized
block at //1 because instance
is null
.null
, but before the constructor executes. null
. Because it is not, thread 2 returns the instance
reference to a fully constructed, but partially initialized, Singleton
object. Singleton
object by running its constructor and returns a reference to it. ?
?
4.早期初始化
public class SingletonTest{private static SingletonTest instance = new SingletonTest();private SingletonTest() {System.out.println("create instance");}public static SingletonTest getInstance() {return instance;}}
?
参考:http://www.ibm.com/developerworks/library/j-dcl.html?S_TACT=105AGX52&S_CMP=cn-a-j