复习单例模式

 基本的单例模式:

 

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  

  1. Thread 1 enters the getInstance() method.

  2. Thread 1 enters the synchronized block at //1 because instance is null.

  3. Thread 1 proceeds to //3 and makes instance non-null, but before the constructor executes.

  4. Thread 1 is preempted by thread 2.

  5. Thread 2 checks to see if instance is null. Because it is not, thread 2 returns the instance reference to a fully constructed, but partially initialized, Singleton object.

  6. Thread 2 is preempted by thread 1.

  7. Thread 1 completes the initialization of the 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值