標籤:final run thread java設計模式 單例對象 類載入 rto imp 多線程
一、單例模式(Singleton)
1、單例模式應用情境:
①Servlet
②工作管理員
③連結池
④Spring中每個 bean 預設是單例
⑤網站計數器
2、單例要求
①構造器私人
②私人的靜態變數
③公用的靜態可以訪問私人的靜態變數的方法
結論:由結果可以得知單例模式為一個物件導向的應用程式提供了對象惟一的訪問點,不管它實現何種功能,整個應用程式都會同享一個執行個體對象。
二、單例模式的實現方式
1、餓漢式
安全執行緒、立即載入、資源使用率低、調用效率高
package cn.com.zfc.gof01.singleton;
/**
*
* @title Singleton01
* @describe 餓漢式實現單例模式
* @author 張富昌
* @date 2017年3月27日上午8:40:02
*/
public class Singleton01 {
// 天然的安全執行緒的,類載入是立即載入這個執行個體
private static Singleton01 instance = new Singleton01();
/ 構造器私人化
private Singleton01() {
}
// 方法沒有同步,效率比較高
public static Singleton01 getInstance() {
return instance;
}
}
2、懶漢式
安全執行緒、消極式載入、資源使用率高、調用效率低
package cn.com.zfc.gof01.singleton;
/**
*
* @title Singleton02
* @describe 懶漢式實現單例模式
* @author 張富昌
* @date 2017年3月27日上午8:45:42
*/
public class Singleton02 {
private static Singleton02 instance = null;
//構造其私人化
private Singleton02() {
}
//公用,同步,靜態
public static synchronized Singleton02 getInstance() {
if (instance == null) {
instance = new Singleton02();
}
return instance;
}
}
3、雙重檢索式
安全執行緒、消極式載入、資源使用率高、調用效率高、但不穩定
package cn.com.zfc.gof01.singleton;
/**
*
* @title Singleton03
* @describe 雙重檢測鎖式實現單例模式(不建議使用)
* @author 張富昌
* @date 2017年3月27日上午8:52:59
*/
public class Singleton03 {
private static Singleton03 instance = null;
private Singleton03() {
}
public static Singleton03 getInstance() {
if (instance == null) {
Singleton03 sc;
synchronized (Singleton03.class) {
sc = instance;
if (sc == null) {
synchronized (Singleton03.class) {
if (sc == null) {
sc = new Singleton03();
}
}
instance = sc;
}
}
}
return instance;
}
}
4、靜態內部類式(相比於懶漢式更好)
安全執行緒、消極式載入、資源使用率高、調用效率高
package cn.com.zfc.gof01.singleton;
/**
*
* @title Singleton04
* @describe 靜態內部類式實現單例模式
* @author 張富昌
* @date 2017年3月27日上午8:54:40
*/
public class Singleton04 {
// 構造器私人化
private Singleton04() {
}
// 靜態內部類
private static class StaticInnerClass {
private static final Singleton04 INSTANCE = new Singleton04();
}
public static Singleton04 getInstance() {
return StaticInnerClass.INSTANCE;
}
}
5、枚舉單例式(相比於餓漢式更好)
安全執行緒、立即載入、可以天然的防止反射和還原序列化
package cn.com.zfc.gof01.singleton;
/**
*
* @title Singleton05
* @describe 枚舉式實現單例模式
* @author 張富昌
* @date 2017年3月27日上午9:01:59
*/
public enum Singleton05 {
// 單例對象
INSTANCE;
// 如果要對該單例對象進行額外的操作,則加入方法
public void singlrtonOperation() {
}
}
三、測試多線程環境下五種建立單例模式的效率
package cn.com.zfc.gof01.singleton.test;
import java.util.concurrent.CountDownLatch;
import cn.com.zfc.gof01.singleton.Singleton05;
/**
*
* @title SingletonTest
* @describe 測試多線程環境下五種建立單例模式的效率
* @author 張富昌
* @date 2017年3月27日上午9:24:58
*/
public class SingletonTest {
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
int threadNum = 10;
// A synchronization aid that allows one or more threads to wait until a
// set of operations being performed in other threads completes.
// 計數器(一個線程執行完成就減1)
final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
for (int i = 0; i < threadNum; i++) {
// 多線程測試
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000000; i++) {
// 餓漢式,
// Object o = Singleton01.getInstance();
// 懶漢式,最慢
// Object o = Singleton02.getInstance();
// 雙重檢測鎖式,不穩定,不建議使用
// Object o = Singleton03.getInstance();
// 靜態內部類
// Object o = Singleton04.getInstance();
// 枚舉式
Object o = Singleton05.INSTANCE;
}
// 一個線程執行完成就減1
countDownLatch.countDown();
}
}).start();
}
// 阻塞
countDownLatch.await(); // main線程阻塞,直到計數器變為0,才會繼續往下執行!
long end = System.currentTimeMillis();
System.out.println("總耗時:" + (end - start));
}
}
四、什麼是安全執行緒?
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程啟動並執行結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是安全執行緒的。
或者說:一個類或者程式所提供的介面對於線程來說是原子操作,或者多個線程之間的切換不會導致該介面的執行結果存在二義性,也就是說我們不用考慮同步的問題,那就是安全執行緒的。
Java設計模式GOF之單例模式