Spring事务_03_ThreadLocal与线程同步

Spring事务_ThreadLocal与线程同步_03

ThreadLocal基础知识

  1. 在JDK1.2版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发提供了一种新思路。
  2. ThreadLocal不是一个线程,是线程的一个本地化的一个对象。当工作于多线程中的对象使用ThreadLocal维护变量时,为每个使用该变量的线程分配一个独立的变量副本。让每个线程都可以独立的改变自己的副本,而不影响其他线程的副本。
  3. 线程局部变量并不是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 {
          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 seqNum = new ThreadLocal(){
              @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为每一个线程都提供一份变量,因此可以同时访问而互不影响。

你可能感兴趣的:(Spring事务_03_ThreadLocal与线程同步)