从如下8点来讲解一下:1.ThreadLocal用来解决多线程程序的并发问题2.ThreadLocal并不是一个Thread,而是Thread的局部变量,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本.3.从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。4.线程局部变量并不是Java的新发明,Java没有提供在语言级支持(语法上),而是变相地通过ThreadLocal的类提供支持.5.ThreadLocal类中的方法:(JDK5版本之后支持泛型) void set(T value) 将此线程局部变量的当前线程副本中的值设置为指定值 void remove() 移除此线程局部变量当前线程的值 protected T initialValue() 返回此线程局部变量的当前线程的“初始值” T get() 返回此线程局部变量的当前线程副本中的值6.ThreadLocal的原理: ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本7.自己模拟ThreadLocal: public class SimpleThreadLocal{ private Map valueMap=Collections.synchronizedMap(new HashMap()); public void set(Object newValue){ valueMap.put(Thread.currentThread(),newValue);//键为线程对象,值为本线程的变量副本 } public Object get(){ Thread currentThread=Thread.currentThread(); Object o=valueMap.get(currentThread);//返回本线程对应的变量 if(o==null&&!valueMap.containsKey(currentThread)){ //如果在Map中不存在,放到Map中保存起来 o=initialValue(); valueMap.put(currentThread,o); } return o; } public void remove(){ valueMap.remove(Thread.currentThread()); } public void initialValue(){ return null; } }8.使用ThreadLocal的具体例子: public class SequenceNumber{ //通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 private static ThreadLocal<Integer> seNum=new ThreadLocal<Integer>(){ protected Integer initialValue(){ return 0; } } public Integer getNextNum(){ seNum.set(seNum.get()+1); return seNum.get(); } public static void main(String[] args){ SequenceNumber sn=new SequenceNumber(); //3个线程共享sn,各自产生序列号 TestClient t1 = new TestClient(sn); TestClient t2 = new TestClient(sn); TestClient t3 = new TestClient(sn); t1.start(); t2.start(); t3.start(); } private static class TestClient extends Thread{ private SequenceNumber sn; public TestClient(SequenceNumber sn){ this.sn=sn; } public void run(){ //每个线程打印3个序列号 for(int i=0;i<3;i++){ System.out.println("thread["+Thread.currentThread().getName()+",sn["+sn.getNextNum()+"]"); } } } }
转载请注明原文地址: https://ju.6miu.com/read-4866.html