单例模式-ThreadLocal线程单例

最后更新于:2022-08-15 13:30:55

ThreadLocal线程单例不能保证一个单例全局唯一,但是可以保证线程唯一

代码

public class ThreadLocalInstance {
    private static final ThreadLocal theadLocalInstance = new ThreadLocal() {
        @Override
        protected ThreadLocalInstance initialValue() {
            return new ThreadLocalInstance();
        }
    };

    private ThreadLocalInstance() {

    }

    public static ThreadLocalInstance getInstance() {
        return theadLocalInstance.get();
    }
}

public class T extends Thread {
    @Override
    public void run() {
        ThreadLocalInstance instance = ThreadLocalInstance.getInstance();
        System.out.println(Thread.currentThread().getName() + " " + instance);
    }
}

多线程测试

public class Test {

    public static void main(String[] args) {
        Thread t1 = new T();
        Thread t2 = new T();
        t1.start();
        t2.start();
    }
}

结果

Thread-1 com.design.pattern.creational.singleton.ThreadLocalInstance@654e4f0e
Thread-0 com.design.pattern.creational.singleton.ThreadLocalInstance@3d3e384b

分别再两个线程中获取单例,结果是不同的
单线程测试

public class T extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " " + ThreadLocalInstance.getInstance());
        System.out.println(Thread.currentThread().getName() + " " + ThreadLocalInstance.getInstance());
        System.out.println(Thread.currentThread().getName() + " " + ThreadLocalInstance.getInstance());

    }
}

结果

Thread-1 com.design.pattern.creational.singleton.ThreadLocalInstance@3d3e384b
Thread-0 com.design.pattern.creational.singleton.ThreadLocalInstance@3d6f32ba
Thread-1 com.design.pattern.creational.singleton.ThreadLocalInstance@3d3e384b
Thread-0 com.design.pattern.creational.singleton.ThreadLocalInstance@3d6f32ba
Thread-1 com.design.pattern.creational.singleton.ThreadLocalInstance@3d3e384b
Thread-0 com.design.pattern.creational.singleton.ThreadLocalInstance@3d6f32ba

同一个线程内的单例是相同的。

ThreadLocal会为每一个线程提供一个独立的变量副本,本身ThreadLocal是基于ThreadLocalMap实现的,在get时默认使用的ThreadLocalMap,不用指定Key,维持了线程之间的隔离。隔绝了多个线程之间的访问冲突,对于多线程之间的资源共享的问题。用同步锁就是用时间换空间,使用ThreadLocal就是用空间换时间。