技术学习笔记
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode

3.5线程变量私有

如果需要线程间进行变量共享,可以把变量定义为 public static.

如果需要线程内部的变量共享,可以使用 ThreadLocal.

1. ThreadLocal

public static ThreadLocal t = new ThreadLocal();

ThreadLocal 具有 get() 和 set() 方法,不同线程拥有自己的域。

子线程MyThread.java
public class MyThread extends Thread{
    @Override
    public void run(){
        if (Run.t.get()==null){
            System.out.println("无");
            Run.t.set("子线程数据");
        }
        System.out.println(Run.t.get());
    }
}
主线程 Run.java
public class Run {
  public static ThreadLocal t = new ThreadLocal();

  public static void main(String[] args) {

      MyThread s = new MyThread();
      s.start();

      if (t.get() == null){
          System.out.println("未有值");
          t.set("Hi");
      }
      System.out.println(t.get());

  }

运行结果

未有值
Hi

子线程数据

这表明,不同线程去访问同一静态域 t,所得到的内容是不一样的。每个线程只能取得属于自己的那一份

若需要给 ThreadLocal 设置初始值

可以继承 ThreadLocal 并且重写值初始化方法。

public class MyThreadLocal extends ThreadLocal{
    @Override
    protected Object initialValue(){
        return "fine";
    }
}

2.InheritableThreadLocal

public static ThreadLocal t = new InheritableThreadLocal();

线程值继承

当前线程的值,第一次访问(set 或者 get)之后才生效,才可被继承。

  • 父线程的值被访问过之后,子线程可以继承父线程的值,但子线程值修改(set)对父线程没有影响。

  • 若父线程的值未被访问,子线程访问所得到的值是默认值。

    子线程访问到的是默认值
    public class Run {
      public static ThreadLocal t = new MyInheritableThreadLocal();
    
      public static void main(String[] args) throws InterruptedException {
          MyThread s = new MyThread();
          s.start();
      }
    }
    

    运行结果

    fine

    父线程的值有被访问,则子线程会继承
    public class Run {
      public static ThreadLocal t = new MyInheritableThreadLocal();
    
      public static void main(String[] args) throws InterruptedException {
    
          System.out.println(t.get());//父线程的值有被访问
          MyThread s = new MyThread();
          s.start();
      }
    }
    

    运行结果

    fine
    fineHa

  • 父线程修改了值,并且执行了其他语句之后,子线程再来继承所得到的值就是新的值。

  • 如果在子线程获取值的时候,父线程修改了值,那么子线程获取到的是旧的值。

  • 若想要在继承的同时对子线程的值进行修改,可以重写 childValue 方法。

    MyInheritableThreadLocal.java
      public class MyInheritableThreadLocal extends InheritableThreadLocal{
      @Override
      protected Object initialValue(){
          return "fine";
      }
      @Override
      protected Object childValue(Object parentValue){
          return parentValue + "Ha";
      }
    }