单例设计模式-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>(){
        @Override
        protected 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 {
    @Override
    public 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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值