單個線程範圍内的資料共享,就是確定目前的線程在執行的過程中,各個子產品所引用的資料是一份,且所引用的資料不會因為其他線程的操作而變化。
以下是一段沒有達到線程内資料共享的代碼(參考自傳智播客視訊)
public class ThreadScopeShareData
{
//用于存放随機産生的資料
static int data = 0;
public static void main(String[] args)
{
//線程1
new Thread(new Runnable()
{
@Override
public void run()
{
data = new Random().nextInt(1000);
System.out.println(Thread.currentThread().getName()
+ "has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
//線程2
new Thread(new Runnable()
{
@Override
public void run()
{
data = new Random().nextInt(1000);
System.out.println(Thread.currentThread().getName()
+ "has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
}
}
class A
{
public void getData()
{
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data value:" + ThreadScopeShareData.data);
}
}
class B
{
public void getData()
{
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data value:" + ThreadScopeShareData.data);
}
}
控制台輸出:
根據控制台的結果,可以看出,由于定義了static的變量存儲資料,那麼當線程2更改了data資料後,線程1中 A子產品和B子產品取出的和當初線程1放入的不是一個值,如何解決這個問題呢?見如下代碼:
一、使用全局的map變量實作
public class ThreadScopeShareData
{
//用于存放随機産生的資料
//static int data = 0;
/*
* 使用map類型的變量取代int類型的變量
*/
static Map<Thread, Integer> map = new HashMap<Thread, Integer>();
public static void main(String[] args)
{
//線程1
new Thread(new Runnable()
{
@Override
public void run()
{
//data = new Random().nextInt(1000);
int data = new Random().nextInt(1000);
//用目前線程作為key,将目前線程産生的随機數,存入map中
map.put(Thread.currentThread(), data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
//線程2
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//用目前線程作為key,将目前線程産生的随機數,存入map中
map.put(Thread.currentThread(), data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
}
}
class A
{
public void getData()
{
//使用目前線程作為map的key去取出map中對應的value
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.map.get(Thread.currentThread()));
}
}
class B
{
public void getData()
{
//使用目前線程作為map的key去取出map中對應的value
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.map.get(Thread.currentThread()));
}
}
二、使用ThreadLocal類,實作單個線程範圍内 單個變量的資料共享
public class ThreadScopeShareData
{
/*
* 使用ThreadLocal
*/
static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
public static void main(String[] args)
{
//線程1
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将目前線程産生的随機數,存入threadLocal中
threadLocal.set(data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
//線程2
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将目前線程産生的随機數,存入threadLocal中
threadLocal.set(data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
}
}
class A
{
public void getData()
{
//從threadLocal中取出value
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.threadLocal.get());
}
}
class B
{
public void getData()
{
//從threadLocal中取出value
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data value:"
+ ThreadScopeShareData.threadLocal.get());
}
}
三、使用ThreadLocal實作 單個線程内 多個變量的資料共享
實作多個資料的共享可以使用Map去存放資料,這裡就不說了 就是把ThreadLocal中的Integer替換成Map即可,主要貼一下使用對象存儲多個變量的代碼實作
①建立一個用于存放共享資料的類
/**
* 存放共享資料的對象
* @author ***
*
*/
class ShareDataObj
{
/**
* threadLocal
*/
private static ThreadLocal<ShareDataObj> threadLocal =
new ThreadLocal<ShareDataObj>();
private ShareDataObj()
{
}
/**
* 傳回從ThreadLocal中取出目前線程的ShareDataObj對象
* @return
*/
public static ShareDataObj getInstance4currentThread()
{
//從threadLocal變量中取出目前線程的ShareDataObj對象
ShareDataObj dataObj = threadLocal.get();
if(dataObj == null)
{
//1、建立一個新的對象
dataObj = new ShareDataObj();
//2、将建立的對象放入ShareDataObj對象中
threadLocal.set(dataObj);
}
return dataObj;
}
//data1
private int data1;
//data2
private String data2;
public int getData1()
{
return data1;
}
public void setData1(int data1)
{
this.data1 = data1;
}
public String getData2()
{
return data2;
}
public void setData2(String data2)
{
this.data2 = data2;
}
}
②操作共享資料
public class ThreadScopeShareData
{
public static void main(String[] args)
{
//線程1
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将目前線程産生的随機數,放入資料共享對象中
ShareDataObj.getInstance4currentThread().setData1(data);
ShareDataObj.getInstance4currentThread().setData2("str-" + data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
//線程2
new Thread(new Runnable()
{
@Override
public void run()
{
int data = new Random().nextInt(1000);
//将目前線程産生的随機數,放入資料共享對象中
ShareDataObj.getInstance4currentThread().setData1(data);
ShareDataObj.getInstance4currentThread().setData2("str-" + data);
System.out.println(Thread.currentThread().getName()
+ " has put data:" + data);
//使用A對象輸出資料
new A().getData();
//使用B對象輸出資料
new B().getData();
}
}).start();
}
}
class A
{
public void getData()
{
//從ShareDataObj中取出目前線程的資料共享對象
System.out.println("A :" + Thread.currentThread().getName()
+ ": get data1:"
+ ShareDataObj.getInstance4currentThread().getData1()
+ ", get data2:"
+ ShareDataObj.getInstance4currentThread().getData2());
}
}
class B
{
public void getData()
{
//從ShareDataObj中取出目前線程的資料共享對象
System.out.println("B :" + Thread.currentThread().getName()
+ ": get data1:"
+ ShareDataObj.getInstance4currentThread().getData1()
+ ", get data2:"
+ ShareDataObj.getInstance4currentThread().getData2());
}
}