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、場景構建
.......後續再寫