Define Single ton class in Java
- when you make a constructor of a class private, that particular class can generate only one object. This type of class is known as singleton class.
# Singleton 單例設計模式
- 整個類裡只能有一個實例可以被獲取或使用。
e.g. 代表 JVM 運行環境的 Runtime class
# 要點
- 一個類只能有一個實例(instance)
- 它需要 "自行創建" 。(約束使用者
- 自行向整個系統提供這個實例
- 對外提供獲取的方法
- 可以公開靜態變量
- 也可以用靜態變量的 get 方法來獲取
# 幾種常見形式
# 餓漢式:直接創建對象,不存在線程安全問題
- 直接實例化餓漢式(簡潔直觀)
- 枚舉式(最簡潔)
- 靜態代碼塊餓漢式(適合複雜實例化
# 直接實例化餓漢式
| |
| 1. constructor 設成 private |
| 2. 自行創建,並且用靜態變量保存 |
| 3. 向外提供這個實例 |
| 4. 強調這是一個單例時,可以用 final 這個 keyword |
| */ |
| public class Singleton1 { |
| public static final Singleton INSTANCE = new Singleton(); |
| private Singleton(){ |
| } |
| } |
直接訪問:
| public class TestSingleton1 { |
| public stastic void main(String[] args) { |
| |
| Singleton1 s = Singleton1.INSTANCE; |
| |
| } |
| } |
# 枚舉式
| |
| 1. 枚舉類型,表示該類型的對象是有限的幾個 |
| 2. 我們可以限定為 1 個,那就成了單例了 |
| |
| */ |
| public enum Singleton2 { |
| INSTANCE |
| } |
訪問:
| public class TestSingleton2 { |
| public stastic void main(String[] args) { |
| |
| Singleton1 s = Singleton2.INSTANCE; |
| System.out.print(s); |
| |
| |
| } |
| } |
# 靜態代碼塊餓漢式
如果 constructor 接收的不是常量,是一個在某文件中的變量,那麼就會用到這個模式。
| public class Singleton3 { |
| public static final Singleton3 INSTANCE; |
| private String info; |
| |
| static{ |
| try { |
| Properties pro = new Properties(); |
| |
| INSTANCE = new Singleton3(pro.getProperty("info")); |
| } catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| private Singleton3(String info){ |
| this.info = info; |
| } |
# 懶漢式:延遲創建對象
- 線程不安全(適用於單線程
- 線程安全(適用於多線程
- 靜態內部類形式(適用於多線程
# 線程不安全
| |
| 1. constructor 設成 private |
| 2. 用一個靜態變量保存這個唯一的實例 |
| 3. 提供一個靜態方法來獲取這個實例對象 |
| */ |
| public class Singleton4 { |
| |
| private static final Singleton4 instance; |
| private Singleton4(){ |
| } |
| |
| public static Singleton4 getInstance() { |
| |
| if (instance == null) { |
| instance = new Singleton4(); |
| } |
| |
| return instance; |
| } |
| } |
訪問:
(這裡我沒有用寫多線程的代碼來演示)
| public class TestSingleton4 { |
| public stastic void main(String[] args) { |
| Singleton4 s1 = Singleton4.getInstance(); |
| |
| |
| |
| System.out.print(s1); |
| System.out.print(s2); |
| |
| } |
| } |
# 線程安全時
| |
| 加上鎖 |
| */ |
| public class Singleton5 { |
| |
| private static final Singleton5 instance; |
| private Singleton5(){ |
| } |
| |
| public static Singleton5 getInstance() { |
| synchronized (Singleton5.class) { |
| if (instance == null) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| instance = new Singleton5(); |
| } |
| return instance; |
| } |
| |
| } |
| } |
用同步方法
| public class Singleton5 { |
| |
| private static final Singleton5 instance; |
| private Singleton5(){ |
| } |
| |
| public static synchronized Singleton5 getInstance() { |
| |
| if (instance == null) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| instance = new Singleton5(); |
| } |
| return instance; |
| } |
| } |
訪問:
| public class Test { |
| public static void main (String[] args) throws InterruptedException, ExecutionException { |
| Callable<Singleton5> c = new Callable<Singleton5>() { |
| @Override |
| public Singleton5 call() throws Exception { |
| return Singleton5.getInstance(); |
| } |
| }; |
| ExecutorService es = Executors.newFixedThreadPool(2); |
| Future<Singleton5> f1 = es.submit(c); |
| Future<Singleton5> f2 = es.submit(c); |
| |
| Singleton5 s1 = f1.get(); |
| Singleton5 s2 = f2.get(); |
| |
| System.out.println(s1 == s2); |
| System.out.println(s1); |
| System.out.println(s2); |
| |
| es.shutdown(); |
| |
| } |
| } |
# 再優化
| public class Singleton5 { |
| private static final Singleton5 instance; |
| private Singleton5(){ |
| } |
| |
| public static Singleton5 getInstance() { |
| if (instance == null) { |
| |
| synchronized (Singleton5.class) { |
| if (instance == null) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| instance = new Singleton5(); |
| } |
| } |
| return instance; |
| } |
| |
| } |
| } |
# volatile
| public class Singleton { |
| private static volatile Singleton instance; |
| private Singleton(){} |
| public static Singleton getInstance(){ |
| if (instance == null) { |
| synchronized (Singleton.class) { |
| if (instance == null) { |
| instance = new Singleton(); |
| } |
| } |
| } |
| return instance; |
| } |
| } |
# 靜態內部類
| |
| |
| |
| public class Singleton6 { |
| private Singleton6(){ |
| } |
| private static class Inner { |
| private static final Singleton6 INSTANCE = new Singleton6(); |
| } |
| public static Singleton6 getInstance() { |
| return Inner.INSTANCE; |
| } |
| } |