多線程基礎:爲線程單獨保存數據ThreadLoacl

ThreadLocal

應用場景

當我們多個線程需要對一個公共的變量就行修改,而我們希望這個變量不受其他線程的影響,但我們有不方便所線程同步(線程同步會影響性能),那麼我們可以爲每個線程都設置一個單獨的變量,讓他們自己去修改,此時,我們就可以用上ThreadLocal

  • 下面,我們可以先看一下,多線程下數據同時被多個線程修改,產生的情況:
package com.zty.demo;

import java.util.ResourceBundle;

/**
 * @創建人 zhangtaiyuan
 * @創建時間 2020/6/23 12:49
 * @描述
 */

class Channel{
    private static Message message;
    public static void setMessage(Message msg){
        message = msg;
    }
    public static void send(){
        System.out.println(Thread.currentThread().getName() + "[消息發送] " + message.getInfo());
    }
}
class Message{
    private String info;
    public void setInfo(String info){
        this.info = info;
    }

    public String getInfo() {
        return info;
    }
}
public class LocalDemo {
    public static void main(String[] args) {
        myThread("第一個線程消息","消息發送者A");
        myThread("第二個線程消息","消息發送者B");
        myThread("第三個線程消息","消息發送者C");
    }

    public static void myThread(String msgStr,String threadName){
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo(msgStr);
            Channel.setMessage(msg);
            Channel.send();
        },threadName
        ).start();
    }
}

輸出結果:

消息發送者A[消息發送] 第二個線程消息
消息發送者B[消息發送] 第二個線程消息
消息發送者C[消息發送] 第二個線程消息
添加上ThreadLocal:
  • 此時,我們可以將Message對象放入ThreadLocal中,然後再從ThreadLocal中獲取即可,只需要修改Channel即可
class Channel{
    private static final ThreadLocal<Message> local = new ThreadLocal<>(); //只是修改這個存數據這裏
    public static void setMessage(Message msg){
        local.set(msg);
    }
    public static void send(){
        System.out.println(Thread.currentThread().getName() + "[消息發送] " + local.get().getInfo());
    }
}
整體代碼如下:
package com.zty.demo;

import java.util.ResourceBundle;

/**
 * @創建人 zhangtaiyuan
 * @創建時間 2020/6/23 12:49
 * @描述
 */

class Channel{
    private static final ThreadLocal<Message> local = new ThreadLocal<>(); //只是修改這個存數據這裏
    public static void setMessage(Message msg){
        local.set(msg);
    }
    public static void send(){
        System.out.println(Thread.currentThread().getName() + "[消息發送] " + local.get().getInfo());
    }
}
class Message{
    private String info;
    public void setInfo(String info){
        this.info = info;
    }

    public String getInfo() {
        return info;
    }
}
public class LocalDemo {
    public static void main(String[] args) {
        myThread("第一個線程消息","消息發送者A");
        myThread("第二個線程消息","消息發送者B");
        myThread("第三個線程消息","消息發送者C");
    }

    public static void myThread(String msgStr,String threadName){
        new Thread(()->{
            Message msg = new Message();
            msg.setInfo(msgStr);
            Channel.setMessage(msg);
            Channel.send();
        },threadName
        ).start();
    }
}

原理

其實原理很簡單,在每個ThreadLocal中一個Map,Map是以"當前線程"作爲key存的值,下面是 ThreadLocal.set(T vlue);的源代碼:

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章