Spring事务基础3-ThreadLocal与线程同步##
ThreadLocal基础知识###
- 在JDK1.2版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发提供了一种新思路。
- ThreadLocal不是一个线程,是线程的一个本地化的一个对象。当工作于多线程中的对象使用ThreadLocal维护变量时,为每个使用该变量的线程分配一个独立的变量副本。让每个线程都可以独立的改变自己的副本,而不影响其他线程的副本。
- 线程局部变量并不是Java发明的,其他的语言在语法层面提供了线程的局部变量。
-
ThreadLocal的接口方法
void set(Object value) 设置当前线程的局部变量 public Object get() 该方法返回当前线程所对应的线程局部变量; public void remove() 将当前线程的局部变量的值删除。jdk1.5添加的方法,当线程结束之后,局部变量会被回收。 protected Object initialValue() 返回该局部变量的初始值,这个方法是protected修饰的,是被用来子类覆盖的。 当第一次调用get或者set方法才会被调用。
JDK1.5之后,ThreadLocal开始支持泛型。
ThreadLocal的实现思路很简单,在ThreadLocal类中维护一个Map,用户存储线程变量的副本,Map中的元素的键为线程的对象,而值对应线程的变量副本。
/** * ThreadLocal 实现原理 * Created by Administrator on 2017/5/30. */ public class SimpleThreadLocal<T> { private Map valeMap = Collections.synchronizedMap(new HashMap()); public void set(T newValue){ valeMap.put(Thread.currentThread(),newValue); } public T get(){ Thread currentThread = Thread.currentThread(); T o = (T) valeMap.get(currentThread); if(o==null&&!valeMap.containsKey(currentThread)){ o = initvalValue(); valeMap.put(currentThread,o); } return o; } protected T initvalValue(){ return null; } }
-
ThreadLocal使用
/** * ThreadLocal实例 * Created by Administrator on 2017/5/30. */ public class SequenceNumber { private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return 0; } }; public int getNextNum(){ seqNum.set(seqNum.get()+1); return seqNum.get(); } public static void main(String[] args) { SequenceNumber sn = new SequenceNumber(); TestClient testClient1= new TestClient(sn); TestClient testClient2= new TestClient(sn); TestClient testClient3= new TestClient(sn); testClient1.start(); testClient2.start(); testClient3.start(); } private static class TestClient extends Thread{ private SequenceNumber sn; public TestClient(SequenceNumber sn){ this.sn = sn; } @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("thread["+ Thread.currentThread().getName()+"]sn["+sn.getNextNum()+"]"); } } } }
-
执行结果:
thread[Thread-1]sn[1]
thread[Thread-0]sn[1]
thread[Thread-0]sn[2]
thread[Thread-0]sn[3]
thread[Thread-1]sn[2]
thread[Thread-1]sn[3]
thread[Thread-2]sn[1]
thread[Thread-2]sn[2]
thread[Thread-2]sn[3]
ThreadLocalshi使用空间换取时间的思想,访问并行化,对象独享化。synchroniz仅提供一份变量,让不同的线程排队去访问,而ThreadLocal为每一个线程都提供一份变量,因此可以同时访问而互不影响。