单例设计模式-ThreadLocal线程单例
生活随笔
收集整理的這篇文章主要介紹了
单例设计模式-ThreadLocal线程单例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
package com.learn.design.pattern.creational.singleton;/*** 是基于ThreadLocal的* 所以必不可少要使用這個類* * 我們看一下這個類* ThreadLocal會為每一個線程提供一個獨立 的線程復本* 本身ThreadLocal是基于static class ThreadLocalMap這個類來實現的* 所以我們在調用它的get方法的時候呢* 默認走的就是這個map* 不用指定key* 他維持了線程間的隔離* 接著回來* 那ThreadLocal隔離了多個線程* 對數據的訪問沖突* 那對于多線程資源共享的問題* 我們想象一下* 我們使用同步鎖* 那其實是以時間換空間的方式* 因為要排隊* 那如果要使用ThreadLocal呢* 就是空間換時間的方式* 很簡單* 可以創建很多對象* 至少在一個線程里* 創建一個* 但是對于這個線程* 他獲取這個對象* 是唯一的* 正如Test這個主函數* 所執行的結果一樣* main里面拿的都是同一個* 基于ThreadLocal帶引號的單例模式呢* 為每個線程都提供了一個對象* 因此在多線程訪問的時候* 相互不會影響* 那這個就是基于ThreadLocal帶引號的單例模式實現方案* * * * @author Leon.Sun**/
public class ThreadLocalInstance {/*** 這個ThreadLocal里面放的泛型* 肯定就是我們的這個對象* 那名字也叫這個類名吧* 然后我們直接重寫里面的方法* 重寫初始化方法* 我們可以認為這個是一個匿名類* * */private static final ThreadLocal<ThreadLocalInstance> threadLocalInstanceThreadLocal= new ThreadLocal<ThreadLocalInstance>(){@Overrideprotected ThreadLocalInstance initialValue() {/*** 這里return很簡單* 初始化的時候直接new一個這樣的對象* 那這塊就聲明好了* 屬于這個類比較重要的初始化* * */return new ThreadLocalInstance();}};/*** 把他的私有構造器補上* * */private ThreadLocalInstance(){}/*** 然后對外開放一個getInstance的方法* 返回的肯定是這個對象* * * @return*/public static ThreadLocalInstance getInstance(){/*** 直接從threadLocalInstanceThreadLocal對象中get* 那這個單例模式就寫完了* 注意它是帶引號的單例* 那么現在測試一下* 還是來到Test里面* * */return threadLocalInstanceThreadLocal.get();}
}
package com.learn.design.pattern.creational.singleton;public class T implements Runnable {@Overridepublic void run() {
// LazySingleton lazySingleton = LazySingleton.getInstance();
// System.out.println(Thread.currentThread().getName()+" "+lazySingleton);
// LazyDoubleCheckSingleton instance = LazyDoubleCheckSingleton.getInstance();
// StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();;// ContainerSingleton.putInstance("object",new Object());
// Object instance = ContainerSingleton.getInstance("object");ThreadLocalInstance instance = ThreadLocalInstance.getInstance();System.out.println(Thread.currentThread().getName()+" "+instance);}
}
package com.learn.design.pattern.creational.singleton;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// LazySingleton lazySingleton = LazySingleton.getInstance();/*** 首先主線程拿到的對象是同一個ThreadLocalInstance@7852e922* 注意這里全部都是ThreadLocalInstance@7852e922* Thread0拿到的是@4d25007* Thread1拿到的是@2dec1376* * */System.out.println("main thread"+ThreadLocalInstance.getInstance());System.out.println("main thread"+ThreadLocalInstance.getInstance());System.out.println("main thread"+ThreadLocalInstance.getInstance());System.out.println("main thread"+ThreadLocalInstance.getInstance());System.out.println("main thread"+ThreadLocalInstance.getInstance());System.out.println("main thread"+ThreadLocalInstance.getInstance());/*** 因為ThreadLocal是基于線程的* 所以我們把T里面的代碼改一下* 這兩個線程拿到的對象 并不是同一個* 那我們想象一下* 現在Main本身是一個線程* 這里面又開了兩個線程* 那如果在main里面拿呢* * */Thread t1 = new Thread(new T());Thread t2 = new Thread(new T());t1.start();t2.start();System.out.println("program end");// HungrySingleton instance = HungrySingleton.getInstance();
// EnumInstance instance = EnumInstance.getInstance();
// instance.setData(new Object());// ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
// oos.writeObject(instance);// File file = new File("singleton_file");
// ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));// HungrySingleton newInstance = (HungrySingleton) ois.readObject();
// EnumInstance newInstance = (EnumInstance) ois.readObject();// System.out.println(instance.getData());
// System.out.println(newInstance.getData());
// System.out.println(instance.getData() == newInstance.getData());// Class objectClass = HungrySingleton.class;
// Class objectClass = StaticInnerClassSingleton.class;// Class objectClass = LazySingleton.class;
// Class objectClass = EnumInstance.class;// Constructor constructor = objectClass.getDeclaredConstructor();
// Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
//
// constructor.setAccessible(true);
// EnumInstance instance = (EnumInstance) constructor.newInstance();
// EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);//
// LazySingleton newInstance = (LazySingleton) constructor.newInstance();
// LazySingleton instance = LazySingleton.getInstance();// StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
// StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();// HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();
// HungrySingleton instance = HungrySingleton.getInstance();// System.out.println(instance);
// System.out.println(newInstance);// System.out.println(instance == newInstance);// EnumInstance instance = EnumInstance.getInstance();
// instance.printTest();}
}
基于ThreadLocal的這種單例寫法,那這個單例可能就要畫一個引號了,因為他不能保證整個應用全局唯一,但是他可以保證線程唯一,那怎么理解呢,我們通過coding吧,首先我們創建一個類,ThreadLocalInstance
?
總結
以上是生活随笔為你收集整理的单例设计模式-ThreadLocal线程单例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单例设计模式-容器单例
- 下一篇: 享元设计模式coding