單例模式有不少的變種,餓漢模式變化不大很少說java
非線程安全的懶漢模式安全
public class LazySingletonDemo { private static LazySingletonDemo instance; public static LazySingletonDemo getInstance() { if (instance == null) { instance = new LazySingletonDemo(); } return instance; } }
線程安全的懶漢模式多線程
這種狀況使用場景不是不少,除非特殊的狀況下,假如只是單純的做爲工具類或者存放常量這種做用的話,考慮多線程安全沒有太大意義,多new出來的對象失去引用很快會被GC掉,除非一瞬間併發量爆炸,同時new了超多的對象(真遇到了那得放鞭炮)併發
1.使用synchronized工具
public class LazySingletonDemo { private static LazySingletonDemo instance; public static LazySingletonDemo getInstance() { System.out.println(Thread.currentThread().getName() + " 1"); if (instance == null) { System.out.println(Thread.currentThread().getName() + " 2"); synchronized (LazySingletonDemo.class) { System.out.println(Thread.currentThread().getName() + " 3"); if (instance == null) { System.out.println(Thread.currentThread().getName() + " 4"); instance = new LazySingletonDemo(); } } } return instance; } public static void main(String[] args) { Runnable r = new Runnable() { public void run() { LazySingletonDemo.getInstance(); } }; Thread t1 = new Thread(r, "t1"); Thread t2 = new Thread(r, "t2"); Thread t3 = new Thread(r, "t3"); Thread t4 = new Thread(r, "t4"); Thread t5 = new Thread(r, "t5"); Thread t6 = new Thread(r, "t6"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); } }
輸出性能
t1 1 t6 1 t6 2 t3 1 t3 2 t4 1 t4 2 t2 1 t6 3 t5 1 t1 2 t5 2 t6 4 t2 2 t5 3 t2 3 t1 3 t4 3 t3 3
能夠看出,6個線程都進入了第1,2,3步驟,可是進入到new的步驟4只有一個線程線程
這裏不把鎖放到方法上的緣由是,每次拿實例的時候都要鎖,很是影響性能,而只有開頭new的時候才須要鎖code
2.使用Lock對象
public class LazySingletonDemo { private static LazySingletonDemo instance; private static ReentrantLock lock = new ReentrantLock(); public static LazySingletonDemo getInstance() { System.out.println(Thread.currentThread().getName() + " 1"); if (instance == null) { System.out.println(Thread.currentThread().getName() + " 2"); try { lock.lock(); System.out.println(Thread.currentThread().getName() + " 3"); if (instance == null) { System.out.println(Thread.currentThread().getName() + " 4"); instance = new LazySingletonDemo(); } } finally { System.out.println(Thread.currentThread().getName() + " 5"); lock.unlock(); } } return instance; } public static void main(String[] args) throws InterruptedException { Runnable r = new Runnable() { public void run() { LazySingletonDemo.getInstance(); } }; Thread t1 = new Thread(r, "t1"); Thread t2 = new Thread(r, "t2"); Thread t3 = new Thread(r, "t3"); Thread t4 = new Thread(r, "t4"); Thread t5 = new Thread(r, "t5"); Thread t6 = new Thread(r, "t6"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); } }
輸出get
t1 1 t3 1 t6 1 t6 2 t4 1 t4 2 t2 1 t6 3 t3 2 t5 1 t5 2 t1 2 t6 4 t2 2 t6 5 t4 3 t4 5 t3 3 t3 5 t5 3 t5 5 t1 3 t1 5 t2 3 t2 5
同上
至於Synchronized和Lock的區別就不說了,網上都有