由淺入深全面解析threadlocal

1、ThreadLocal介紹

1.1、ThreadLocal官方介紹

 

總結:

1、線程併發:在多線程併發的場景下

2、傳遞數據:我們可以通過ThreadLocal在同一線程,不同組件中傳遞公共變量

3、線程隔離:每個線程的變量都是獨立的,不會相互影響

1.2、ThreadLocal基本使用

1.2.1、常用方法

1.2.2、常用方法

/**
 * 需求:線程隔離
 *      在多線程併發的情況下,每個線程中的變量都是相互獨立的
 *      線程A:    設置(變量1)   獲取(變量1)
 *      線程B:    設置(變量2)   獲取(變量2)
 */
public class Mydemo01
{
    //變量
    private String content;

    private String getContent()
    {
        return content;
    }

    private void setContent(String content)
    {
        this.content = content;
    }

    public static void main(String[] args)
    {
        Mydemo01 demo = new Mydemo01();

        for(int i = 0; i < 5; i++)
        {
            Thread thread = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    demo.setContent(Thread.currentThread().getName() + "的數據");
                    System.out.println("-----------------------------");
                    System.out.println(Thread.currentThread().getName() + "----->" + demo.getContent());
                }
            });

            thread.setName("線程" + i);
            thread.start();
        }
    }
}

 這樣就會出現這種現象:

導致同一個線程訪問到別的線程的變量 

通過threadLocal來解決線程的這種現象

/**
 * 需求:線程隔離
 *      在多線程併發的情況下,每個線程中的變量都是相互獨立的
 *      線程A:    設置(變量1)   獲取(變量1)
 *      線程B:    設置(變量2)   獲取(變量2)
 */
public class Mydemo01
{
    ThreadLocal<String> t1 = new ThreadLocal<>();

    //變量
    private String content;

    private String getContent()
    {
        //return content;
        String s = t1.get();
        return s;
    }

    private void setContent(String content)
    {
        //this.content = content;
        //變量content綁定到當前線程
        t1.set(content);
    }

    public static void main(String[] args)
    {
        Mydemo01 demo = new Mydemo01();

        for(int i = 0; i < 5; i++)
        {
            Thread thread = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    demo.setContent(Thread.currentThread().getName() + "的數據");
                    System.out.println("-----------------------------");
                    System.out.println(Thread.currentThread().getName() + "----->" + demo.getContent());
                }
            });

            thread.setName("線程" + i);
            thread.start();
        }
    }
}

1.3、ThreadLocal類與synchronized關鍵字

1.3.1、synchronized同步方式

/**
 * 需求:線程隔離
 *      在多線程併發的情況下,每個線程中的變量都是相互獨立的
 *      線程A:    設置(變量1)   獲取(變量1)
 *      線程B:    設置(變量2)   獲取(變量2)
 */
public class Mydemo02
{

    //變量
    private String content;

    private String getContent()
    {
        return content;
    }

    private void setContent(String content)
    {
        this.content = content;
    }

    public static void main(String[] args)
    {
        Mydemo02 demo = new Mydemo02();

        for(int i = 0; i < 5; i++)
        {
            Thread thread = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    synchronized (Mydemo02.class)
                    {
                        demo.setContent(Thread.currentThread().getName() + "的數據");
                        System.out.println("-----------------------------");
                        System.out.println(Thread.currentThread().getName() + "----->" + demo.getContent());
                    }
                  }
            });

            thread.setName("線程" + i);
            thread.start();
        }
    }
}

     雖然ThreadLocal模式與synchronized關鍵字都用於處理多線程併發訪問變量的問題,不過兩者處理問題的角度和思路不同

  synchronized ThreadLocal
原理 同步機制採用"以時間換空間"的方式,只提供了一份變量,讓不同的線程排隊訪問 ThreadLocal採用“以空間換時間”的方式,爲每一個線程都提供了一份變量的副本,從而實現同時訪問而相互不干擾
側重點 多個線程之間訪問資源的同步 多線程中讓每個線程之間的數據相互隔離

總結:在剛剛的案例中,雖然使用ThreadLocal和Synchronized都能夠解決問題,但是使用ThreadLocal更爲合理,因爲這樣可以使線程程序擁有更高的併發性

2、應用場景——事務案例 

2.1、轉賬案例 

2.1.1、場景構建 

.......後續再寫 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章