天天看點

java多線程之線程副本(ThreadLocal)ThreadLocal了解使用

ThreadLocal了解使用

1.threadlocal是一種多線程間并發通路變量的解決方案,采取以空間換時間的方式,不使用鎖,為每個線程提供變量的獨立副本,以保障線程安全

2.背景:變量分為類變量 執行個體變量和局部變量(局部變量是線程安全的不用考慮)

情景一:ThreadLocal存儲類變量的時候存線上程安全問題,所有線程共享類變量,變量的改變會導緻所有線程副本變量的改變

private ThreadLocal local =new ThreadLocal();

    private static List<String> list=new ArrayList<>();

    public void setName(String name) {
        list.add(name);
        list.add("test");
        //因為在main方法裡面運作是以注意區分主線程和子線程(ThreadLocal和線程綁定的)
       // local.set(list);(這裡使用隻能是主線程ThreadLocal綁定了list)
        System.out.println(Thread.currentThread());
    }

    @Override
    public void run() {
        local.set(list);
        System.out.println(local.get());
        System.out.println(Thread.currentThread());

    }
//運作
 public static void main(String[] asd){
        local al =   new local();
        Thread thread =new Thread(new local());
           Thread thread1=new Thread(new local());
        try {
            Thread.sleep(1000);
            al.setName("123");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.start();
          thread1.start();
        System.out.println(Thread.currentThread());
        
結果:[123, test] 
           [123, test]

           

情景二:ThreadLocal存儲的是實力變得時候也會存線上程安全問題,當多個線程處理同一個執行個體變量的時候,執行個體變量的變化會導緻多個線程的執行個體副本都會發生變化,如果一個線程處理一個執行個體就不會發生安全問題,并且保證執行個體變量副本的修改互不影響。

private ThreadLocal local =new ThreadLocal();

    private List<String> list=new ArrayList<>();

    public void setName(String name) {
        list.add(name);
        list.add("test");
        //因為在main方法裡面運作是以注意區分主線程和子線程(ThreadLocal和線程綁定的)
       // local.set(list);(這裡使用隻能是主線程ThreadLocal綁定了list)
        System.out.println(Thread.currentThread());
    }

    @Override
    public void run() {
        local.set(list);
        System.out.println(local.get());
        System.out.println(Thread.currentThread());

    }
//運作
 public static void main(String[] asd){
        local al =   new local();
        Thread thread =new Thread(al);
           Thread thread1=new Thread(al);
        try {
            Thread.sleep(1000);
            al.setName("123");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.start();
          thread1.start();
        System.out.println(Thread.currentThread());
        
結果:[123, test] 
           [123, test]

           

備注:重點是厘清楚主線程(目前線程,例如Thread.sleep就是指的是目前線程也就是代碼正在運作所線上程)和子線程

繼續閱讀