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
诸葛