赞
踩
什么是ThreadLocal变量
ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:
ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。
总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。
ThreadLocal实现原理
首先 ThreadLocal 是一个泛型类,保证可以接受任何类型的对象。
因为一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。而我们使用的 get()、set() 方法其实都是调用了这个ThreadLocalMap类对应的 get()、set() 方法
本地线程设置数据,获取数据
package com.ln.concurrent.chapter10; /** * @ProjectName: java-concurrency * @Package: com.ln.concurrent.chapter10 * @Name:ThreadLocalSimpleTest * @Author:linianest * @CreateTime:2020/3/28 21:00 * @version:1.0 * @Description TODO: ThreadLocal线程 */ public class ThreadLocalSimpleTest { /** * threadlocal 通过initialValue设置初始值 */ private static ThreadLocal<String> threadLocal = new ThreadLocal() { @Override protected Object initialValue() { return "Alex"; } }; public static void main(String[] args) throws InterruptedException { // threadLocal.set("Alex"); Thread.sleep(1000); System.out.println(threadLocal.get()); } }
多线程访问本地线程
package com.ln.concurrent.chapter10; import java.util.Arrays; import java.util.Random; /** * @ProjectName: java-concurrency * @Package: com.ln.concurrent.chapter10 * @Name:ThreadLocalComplexTest * @Author:linianest * @CreateTime:2020/3/28 21:40 * @version:1.0 * @Description TODO: 线程ThreadLocal */ public class ThreadLocalComplexTest { private final static ThreadLocal<String> threadlocal = new ThreadLocal<>(); public static final Random random = new Random(System.currentTimeMillis()); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { threadlocal.set("Thread-T1"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + " " + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2 = new Thread(() -> { threadlocal.set("Thread-T2"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + " " + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("==========================="); System.out.println(Thread.currentThread().getName() + " " + threadlocal.get()); } }
自定义threadlocal,使用hashmap存放数据
package com.ln.concurrent.chapter10; import java.util.HashMap; import java.util.Map; /** * @ProjectName: java-concurrency * @Package: com.ln.concurrent.chapter10 * @Name:ThreadLocalSimulator * @Author:linianest * @CreateTime:2020/3/29 14:22 * @version:1.0 * @Description TODO: 自定义实现ThreadLocal */ public class ThreadLocalSimulator<T> { private final Map<Thread, T> storage = new HashMap<>(); public void set(T t) { synchronized (this) { Thread key = Thread.currentThread(); storage.put(key, t); } } public T get() { synchronized (this) { Thread key = Thread.currentThread(); T value = storage.get(key); if (value==null){ return initialValue(); } return value; } } public T initialValue(){ return null; } }
测试
package com.ln.concurrent.chapter10; import java.util.Random; /** * @ProjectName: java-concurrency * @Package: com.ln.concurrent.chapter10 * @Name:ThreadLocalSimulatorTest * @Author:linianest * @CreateTime:2020/3/29 16:31 * @version:1.0 * @Description TODO: 测试ThreadLocalSimulator */ /** * 始终以当前线程作为key值 */ public class ThreadLocalSimulatorTest { private final static ThreadLocalSimulator<String> threadlocal = new ThreadLocalSimulator<String>() { @Override public String initialValue() { return "No Value"; } }; // private final static ThreadLocal<String> threadlocal = new ThreadLocal<>(); public static final Random random = new Random(System.currentTimeMillis()); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { threadlocal.set("Thread-T1"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + " " + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2 = new Thread(() -> { threadlocal.set("Thread-T2"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + " " + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("==========================="); System.out.println(Thread.currentThread().getName() + " " + threadlocal.get()); } }
通过以上的方式,明白了本地线程的原理
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。