線程范圍內(nèi)的共享變量
1. 線程范圍內(nèi)的共享變量的概念
假設有2個線程,一個全局變量 int data。2個線程內(nèi)的代碼共用這一個變量的聲明(data),但它們操作data時,data的值在這2個線程里是獨立的,互不影響的。我們這里所說的互不影響,不是我們之前說的syncronized,(線程1先修改data值,讀取data值,釋放鎖后,線程2才可修改data和讀取data,這樣的話data最終的值還會變?yōu)榫€程2最后修改的值)。我們現(xiàn)在要實現(xiàn)的是,線程1修改了data=1, 線程2也修改了同一個data變量的值為2,data=2,最后線程1回過頭再去讀取時,讀取出的data應該是1(它自己當時放的值就是1),線程2回頭再去讀取data時,讀取的也是它自己的值,2.? 這個data是2個線程的共享變量,但它的值在2個線程范圍內(nèi)各自是獨立的。如下圖所示:
2. 代碼實現(xiàn)
2.1? ?定義全局變量
我們定義如下全局變量:
private static Map
一個map, 其中的key為正在執(zhí)行的線程對象,value就是我們在上面1中所說的data變量(整數(shù))。
在線程1和線程2的代碼中會使用到這個全局變量threadData,通過不同的key來區(qū)分線程,從而獲取到對應線程中所操作的data變量。
其本質(zhì)是利用了Map(key,value)這個數(shù)據(jù)結(jié)構(gòu),實現(xiàn)了共享變量。那么這里的共享變量應該是Map還是Map里的value(整數(shù))呢?從共享變量的角度來講是這個MAP,因為我們2個線程內(nèi)的代碼都使用了同一個變量聲明threadData,? ? ?但是從數(shù)據(jù)在線程內(nèi)獨立的角度來講,我們其實是想讓MAP中的value,這個核心數(shù)據(jù)的值在2個線程內(nèi)是獨立的。? 所以,我們還是看核心數(shù)據(jù),我認為共享變量應是Map里存儲的那個value。
2.2? 編寫2個線程
開啟2個線程,存儲一個data變量的值到 MAP中的value里,到時候讀取的時候,以MAP中的key來區(qū)分,讀取對應線程中 曾經(jīng)存儲過的那個data變量的值。
package testFuture;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadShareData {
private static Map
public static void main(String[] args) {
for(int i=0;i<2;i++){
final int temp = i;
new Thread(new Runnable(){
@Override
public void run() {
int data = temp;
System.out.println(Thread.currentThread().getName()
+ " has modify data :" + data);
threadShareData.put(Thread.currentThread(), data);
new DataReadA().get();
}
}).start();
}
}
static class DataReadA{
public void get(){
int data = threadShareData.get(Thread.currentThread());
System.out.println("DataReadA " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
}
運行日志如下:
Thread-1 has modify data :1
Thread-0 has modify data :0
DataReadA Thread-1 get data :1
DataReadA Thread-0 get data :0
我們使用for循環(huán)創(chuàng)建了2個線程,每一個線程里的run函數(shù)將 for循環(huán)的索引值作為data變量的值存儲在了threadShareData這個map里,同時這個map中的key為當前線程對象:Thread.currentThread()。
這樣我們在調(diào)用DataReadA對象的get函數(shù)時,獲取的是每一個線程對應的value,即剛才存儲的data變量值。在這里我們可以把DataReadA對象看作是一個程序模塊。
那我們再創(chuàng)建一個模塊,DataReadB,看看我們的運行結(jié)果。代碼和運行日志如下,
代碼:
package testFuture;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadShareData {
private static Map
public static void main(String[] args) {
for(int i=0;i<2;i++){
final int temp = i;
new Thread(new Runnable(){
@Override
public void run() {
int data = temp;
System.out.println(Thread.currentThread().getName()
+ " has modify data :" + data);
threadShareData.put(Thread.currentThread(), data);
new DataReadA().get();
new DataReadB().get();
}
}).start();
}
}
static class DataReadA{
public void get(){
int data = threadShareData.get(Thread.currentThread());
System.out.println("DataReadA " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
static class DataReadB{
public void get(){
int data = threadShareData.get(Thread.currentThread());
System.out.println("DataReadB " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
}
日志:
Thread-0 has modify data :0
Thread-1 has modify data :1
DataReadA Thread-1 get data :1
DataReadA Thread-0 get data :0
DataReadB ?Thread-0 get data :0
DataReadB ?Thread-1 get data :1
我們發(fā)現(xiàn)只要是在第一個線程(Thread0)里,無論是DataReadA 還是DataReadB調(diào)用get函數(shù),讀取出來的變量值都是0,因為它當時放的就是0(日志:Thread-0 has modify data :0)。同理,
Thread-1讀出來的值也是它當時存儲的那個變量data,如上述日志:DataReadA Thread-1 get data :1;?DataReadB ?Thread-1 get data :1。
總結(jié):
好了,今天線程范圍內(nèi)共享同一個變量聲明就講到這里,記住兩點就行:1. 共享同一個變量聲明; 2.? 兩個線程內(nèi)要使用的核心數(shù)據(jù)的值,是兩份,修改和讀取都互不干擾。
任務調(diào)度
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。