设计模式课程 设计模式精讲 8-10 单例设计模式-ThreadLocal线程单例

1    课程讲解

1.1  应用场景

2    代码演练

2.1  threadLocal应用

1    课程讲解
1.1  应用场景

多线程的时候:

使用同步锁使用时间换空间的方式,(线程排队时间比较长)

而使用threadlocal使用空间换时间的方式。

基于threadlocal的单例模式,为每一个线程提供了一个对象,多线程访问的时候不会相互影响。

基于ThreadLocal的单例实现,数据库连接池的这种应用场景直接得提高了并发量,并且隔离了线程,不至于因为某一线程数据库连接断开造成全局断开,直接得提高了应用的容错率。但是代码层面要避免混用不同线程产生的单例。

自己理解:其实这种带引号的单例模式(threadLocal)已经不能称为单例模式了,因为同一个单例类,取出来的对象已经不一样了

2    代码演练
2.1  threadLocal应用

测试类:

package com.geely.design.pattern.creational.singleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {

    public static void main(String [] args){
        Thread thread1 = new Thread(new T());
        Thread thread2 = new Thread(new T());
        thread1.start();
        thread2.start();
        System.out.println("结束了!!!");
    }

}

线程类:

package com.geely.design.pattern.creational.singleton;

/**
 * 注:该类为线程类,调用LazySingleton
 */
public class T implements Runnable{

    @Override
    public void run() {
/*        StaticInnerClassSingleton staticInnerClassSingleton = StaticInnerClassSingleton.getInstance();*/
        ThreadLocalInstance threadLocalInstance = ThreadLocalInstance.getInstance();
        System.out.println(Thread.currentThread().getName()+"==="+threadLocalInstance);
    }
}

实体类:

package com.geely.design.pattern.creational.singleton;

public class ThreadLocalInstance {
    /**
     * 预防外部类 实例化本类
     */
    private  ThreadLocalInstance(){

    }

   public static final ThreadLocal<ThreadLocalInstance> threadLocalInstance
           = new ThreadLocal<ThreadLocalInstance>(){
       /**
        * 重写初始化方法
        */
       @Override
       protected ThreadLocalInstance initialValue(){
           return new ThreadLocalInstance();
        }
   };

    /**
     * 获得实例
     * @return
     */
    public static ThreadLocalInstance getInstance(){
       return threadLocalInstance.get();
    }
}

引用类:

  /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

static class ThreadLocalMap { /** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } } }

打印日志:

结束了!!!
Thread-0===com.geely.design.pattern.creational.singleton.ThreadLocalInstance@120f0be
Thread-1===com.geely.design.pattern.creational.singleton.ThreadLocalInstance@75dfb148

Process finished with exit code 0

猜你喜欢

转载自www.cnblogs.com/1446358788-qq/p/11442693.html