X-Spirit
Always Beyond the Time
BlogJava
|
首頁(yè)
|
發(fā)新隨筆
|
發(fā)新文章
|
聯(lián)系
|
聚合
|
管理
隨筆:91 文章:1 評(píng)論:65 引用:0
Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
前面我們介紹了Java當(dāng)中多個(gè)線程搶占一個(gè)共享資源的問(wèn)題。但不論是同步還是重入鎖,都不能實(shí)實(shí)在在的解決資源緊缺的情況,這些方案只是靠制定規(guī)則來(lái)約束線程的行為,讓它們不再拼命的爭(zhēng)搶,而不是真正從實(shí)質(zhì)上解決他們對(duì)資源的需求。
在JDK 1.2當(dāng)中,引入了java.lang.ThreadLocal。它為我們提供了一種全新的思路來(lái)解決線程并發(fā)的問(wèn)題。但是他的名字難免讓我們望文生義:本地線程?
什么是本地線程?
本地線程開(kāi)玩笑的說(shuō):不要迷戀哥,哥只是個(gè)傳說(shuō)。
其實(shí)ThreadLocal并非Thread at Local,而是LocalVariable in a Thread。
根據(jù)WikiPedia上的介紹,ThreadLocal其實(shí)是源于一項(xiàng)多線程技術(shù),叫做Thread Local Storage,即線程本地存儲(chǔ)技術(shù)。不僅僅是Java,在C++、C#、.NET、Python、Ruby、Perl等開(kāi)發(fā)平臺(tái)上,該技術(shù)都已經(jīng)得以實(shí)現(xiàn)。
當(dāng)使用ThreadLocal維護(hù)變量時(shí),它會(huì)為每個(gè)使用該變量的線程提供獨(dú)立的變量副本。也就是說(shuō),他從根本上解決的是資源數(shù)量的問(wèn)題,從而使得每個(gè)線程持有相對(duì)獨(dú)立的資源。這樣,當(dāng)多個(gè)線程進(jìn)行工作的時(shí)候,它們不需要糾結(jié)于同步的問(wèn)題,于是性能便大大提升。但資源的擴(kuò)張帶來(lái)的是更多的空間消耗,ThreadLocal就是這樣一種利用空間來(lái)?yè)Q取時(shí)間的解決方案。
說(shuō)了這么多,來(lái)看看如何正確使用ThreadLocal。
通過(guò)研究JDK文檔,我們知道,ThreadLocal中有幾個(gè)重要的方法:get()、set()、remove()、initailValue(),對(duì)應(yīng)的含義分別是:
返回此線程局部變量的當(dāng)前線程副本中的值、將此線程局部變量的當(dāng)前線程副本中的值設(shè)置為指定值、移除此線程局部變量當(dāng)前線程的值、返回此線程局部變量的當(dāng)前線程的“初始值”。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
還記得我們?cè)诘谌纳习牍?jié)引出的那個(gè)例子么?幾個(gè)線程修改同一個(gè)Student對(duì)象中的age屬性。為了保證這幾個(gè)線程能夠工作正常,我們需要對(duì)Student的對(duì)象進(jìn)行同步。
下面我們對(duì)這個(gè)程序進(jìn)行一點(diǎn)小小的改造,我們通過(guò)繼承Thread來(lái)實(shí)現(xiàn)多線程:
/**
*
*
@author
x-spirit
*/
public
class
ThreadDemo3
extends
Thread{
private
ThreadLocal
<
Student
>
stuLocal
=
new
ThreadLocal
<
Student
>
();
public
ThreadDemo3(Student stu){
stuLocal.set(stu);
}
public
static
void
main(String[] args) {
Student stu
=
new
Student();
ThreadDemo3 td31
=
new
ThreadDemo3(stu);
ThreadDemo3 td32
=
new
ThreadDemo3(stu);
ThreadDemo3 td33
=
new
ThreadDemo3(stu);
td31.start();
td32.start();
td33.start();
}
@Override
public
void
run() {
accessStudent();
}
public
void
accessStudent() {
String currentThreadName
=
Thread.currentThread().getName();
System.out.println(currentThreadName
+
"
is running!
"
);
Random random
=
new
Random();
int
age
=
random.nextInt(
100
);
System.out.println(
"
thread
"
+
currentThreadName
+
"
set age to:
"
+
age);
Student student
=
stuLocal.get();
student.setAge(age);
System.out.println(
"
thread
"
+
currentThreadName
+
"
first read age is:
"
+
student.getAge());
try
{
Thread.sleep(
5000
);
}
catch
(InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(
"
thread
"
+
currentThreadName
+
"
second read age is:
"
+
student.getAge());
}
}
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
貌似這個(gè)程序沒(méi)什么問(wèn)題。但是運(yùn)行結(jié)果卻顯示:這個(gè)程序中的3個(gè)線程會(huì)拋出3個(gè)空指針異常。讀者一定感到很困惑。我明明在構(gòu)造器當(dāng)中把Student對(duì)象set進(jìn)了ThreadLocal里面阿,為什么run起來(lái)之后居然在調(diào)用stuLocal.get()方法的時(shí)候得到的是NULL呢?
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
帶著這個(gè)疑問(wèn),讓我們深入到JDK的代碼當(dāng)中,去一看究竟。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
原來(lái),在ThreadLocal中,有一個(gè)內(nèi)部類叫做ThreadLocalMap。這個(gè)ThreadLocalMap并非java.util.Map的一個(gè)實(shí)現(xiàn),而是利用java.lang.ref.WeakReference實(shí)現(xiàn)的一個(gè)鍵-值對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)其中,key是ThreadLocal類型,而value是Object類型,我們可以簡(jiǎn)單的視為HashMap<ThreadLocal,Object>。
而在每一個(gè)Thread對(duì)象中,都有一個(gè)ThreadLocalMap的引用,即Thread.threadLocals。而ThreadLocal的set方法就是首先嘗試從當(dāng)前線程中取得ThreadLocalMap(以下簡(jiǎn)稱Map)對(duì)象。如果取到的不為null,則以ThreadLocal對(duì)象自身為key,來(lái)取Map中的value。如果取不到Map對(duì)象,則首先為當(dāng)前線程創(chuàng)建一個(gè)ThreadLocalMap,然后以ThreadLocal對(duì)象自身為key,將傳入的value放入該Map中。
ThreadLocalMap getMap(Thread t) {
return
t.threadLocals;
}
public
void
set(T value) {
Thread t
=
Thread.currentThread();
ThreadLocalMap map
=
getMap(t);
if
(map
!=
null
)
map.set(
this
, value);
else
createMap(t, value);
}
而get方法則是首先得到當(dāng)前線程的ThreadLocalMap對(duì)象,然后,根據(jù)ThreadLocal對(duì)象自身,取出相應(yīng)的value。當(dāng)然,如果在當(dāng)前線程中取不到ThreadLocalMap對(duì)象,則嘗試為當(dāng)前線程創(chuàng)建ThreadLocalMap對(duì)象,并以ThreadLocal對(duì)象自身為key,把initialValue()方法產(chǎn)生的對(duì)象作為value放入新創(chuàng)建的ThreadLocalMap中。
public
T get() {
Thread t
=
Thread.currentThread();
ThreadLocalMap map
=
getMap(t);
if
(map
!=
null
) {
ThreadLocalMap.Entry e
=
map.getEntry(
this
);
if
(e
!=
null
)
return
(T)e.value;
}
return
setInitialValue();
}
private
T setInitialValue() {
T value
=
initialValue();
Thread t
=
Thread.currentThread();
ThreadLocalMap map
=
getMap(t);
if
(map
!=
null
)
map.set(
this
, value);
else
createMap(t, value);
return
value;
}
protected
T initialValue() {
return
null
;
}
這樣,我們就明白上面的問(wèn)題出在哪里:我們?cè)趍ain方法執(zhí)行期間,試圖在調(diào)用ThreadDemo3的構(gòu)造器時(shí)向ThreadLocal置入Student對(duì)象,而此時(shí),以ThreadLocal對(duì)象為key,Student對(duì)象為value的Map是被放入當(dāng)前的活動(dòng)線程內(nèi)的。也就是Main線程。而當(dāng)我們的3個(gè)ThreadDemo3線程運(yùn)行起來(lái)以后,調(diào)用get()方法,都是試圖從當(dāng)前的活動(dòng)線程中取得ThreadLocalMap對(duì)象,但當(dāng)前的活動(dòng)線程顯然已經(jīng)不是Main線程了,于是,程序最終執(zhí)行了ThreadLocal原生的initialValue()方法,返回了null。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
講到這里,我想不少朋友一定已經(jīng)看出來(lái)了:ThreadLocal的initialValue()方法是需要被覆蓋的。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
于是,ThreadLocal的正確使用方法是:將ThreadLocal以內(nèi)部類的形式進(jìn)行繼承,并覆蓋原來(lái)的initialValue()方法,在這里產(chǎn)生可供線程擁有的本地變量值。
這樣,我們就有了下面的正確例程:
/**
*
*
@author
x-spirit
*/
public
class
ThreadDemo3
extends
Thread{
private
ThreadLocal
<
Student
>
stuLocal
=
new
ThreadLocal
<
Student
>
(){
@Override
protected
Student initialValue() {
return
new
Student();
}
};
public
ThreadDemo3(){
}
public
static
void
main(String[] args) {
ThreadDemo3 td31
=
new
ThreadDemo3();
ThreadDemo3 td32
=
new
ThreadDemo3();
ThreadDemo3 td33
=
new
ThreadDemo3();
td31.start();
td32.start();
td33.start();
}
@Override
public
void
run() {
accessStudent();
}
public
void
accessStudent() {
String currentThreadName
=
Thread.currentThread().getName();
System.out.println(currentThreadName
+
"
is running!
"
);
Random random
=
new
Random();
int
age
=
random.nextInt(
100
);
System.out.println(
"
thread
"
+
currentThreadName
+
"
set age to:
"
+
age);
Student student
=
stuLocal.get();
student.setAge(age);
System.out.println(
"
thread
"
+
currentThreadName
+
"
first read age is:
"
+
student.getAge());
try
{
Thread.sleep(
5000
);
}
catch
(InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(
"
thread
"
+
currentThreadName
+
"
second read age is:
"
+
student.getAge());
}
}
********** 補(bǔ)疑 ******************
有的童鞋可能會(huì)問(wèn):“你這個(gè)Demo根本沒(méi)體現(xiàn)出來(lái),每個(gè)線程里都有一個(gè)ThreadLocal對(duì)象;應(yīng)該是一個(gè)ThreadLocal對(duì)象對(duì)應(yīng)多個(gè)線程,你這變成了一對(duì)一,完全沒(méi)體現(xiàn)出ThreadLocal的作用。”
那么我們來(lái)看一下如何用一個(gè)ThreadLocal對(duì)象來(lái)對(duì)應(yīng)多個(gè)線程:
/** */
/**
*
*
@author
x-spirit
*/
public
class
ThreadDemo3
implements
Runnable
{
private
ThreadLocal
<
Student
>
stuLocal
=
new
ThreadLocal
<
Student
>
()
{
@Override
protected
Student initialValue()
{
return
new
Student();
}
}
;
public
ThreadDemo3()
{
}
public
static
void
main(String[] args)
{
ThreadDemo3 td3
=
new
ThreadDemo3();
Thread t1
=
new
Thread(td3);
Thread t2
=
new
Thread(td3);
Thread t3
=
new
Thread(td3);
t1.start();
t2.start();
t3.start();
}
@Override
public
void
run()
{
accessStudent();
}
public
void
accessStudent()
{
String currentThreadName
=
Thread.currentThread().getName();
System.out.println(currentThreadName
+
"
is running!
"
);
Random random
=
new
Random();
int
age
=
random.nextInt(
100
);
System.out.println(
"
thread
"
+
currentThreadName
+
"
set age to:
"
+
age);
Student student
=
stuLocal.get();
student.setAge(age);
System.out.println(
"
thread
"
+
currentThreadName
+
"
first read age is:
"
+
student.getAge());
try
{
Thread.sleep(
5000
);
}
catch
(InterruptedException ex)
{
ex.printStackTrace();
}
System.out.println(
"
thread
"
+
currentThreadName
+
"
second read age is:
"
+
student.getAge());
}
}
這里,多個(gè)線程對(duì)象都使用同一個(gè)實(shí)現(xiàn)了Runnable接口的ThreadDemo3對(duì)象來(lái)構(gòu)造。這樣,多個(gè)線程使用的ThreadLocal對(duì)象就是同一個(gè)。結(jié)果仍然是正確的。但是仔細(xì)回想一下,這兩種實(shí)現(xiàn)方案有什么不同呢?
答案其實(shí)很簡(jiǎn)單,并沒(méi)有本質(zhì)上的不同。對(duì)于第一種實(shí)現(xiàn),不同的線程對(duì)象當(dāng)中ThreadLocalMap里面的KEY使用的是不同的ThreadLocal對(duì)象。而對(duì)于第二種實(shí)現(xiàn),不同的線程對(duì)象當(dāng)中ThreadLocalMap里面的KEY是同一個(gè)ThreadLocal對(duì)象。但是從本質(zhì)上講,不同的線程對(duì)象都是利用其自身的ThreadLocalMap對(duì)象來(lái)對(duì)各自的Student對(duì)象進(jìn)行封裝,用ThreadLocal對(duì)象作為該ThreadLocalMap的KEY。所以說(shuō),“ThreadLocal的思想精髓就是為每個(gè)線程創(chuàng)建獨(dú)立的資源副本。”這句話并不應(yīng)當(dāng)被理解成:一定要使用同一個(gè)ThreadLocal對(duì)象來(lái)對(duì)多個(gè)線程進(jìn)行處理。因?yàn)檎嬲脕?lái)封裝變量的不是ThreadLocal。就算是你的程序中所有線程都共用同一個(gè)ThreadLocal對(duì)象,而你真正封裝到ThreadLocalMap中去的仍然是.hashCode()方法返回不同值的不同對(duì)象。就好比線程就是房東,ThreadLocalMap就是房東的房子。房東通過(guò)ThreadLocal這個(gè)中介去和房子里的房客打交道,而房東不管要讓房客住進(jìn)去還是搬出來(lái),都首先要經(jīng)過(guò)ThreadLocal這個(gè)中介。
所以提到ThreadLocal,我們不應(yīng)當(dāng)顧名思義的認(rèn)為JDK里面提供ThreadLocal就是提供了一個(gè)用來(lái)封裝本地線程存儲(chǔ)的容器,它本身并沒(méi)有Map那樣的容器功能。真正發(fā)揮作用的是ThreadLocalMap。也就是說(shuō),事實(shí)上,采用ThreadLocal來(lái)提高并發(fā)行,首先要理解,這不是一種簡(jiǎn)單的對(duì)象封裝,而是一套機(jī)制,而這套機(jī)制中的三個(gè)關(guān)鍵因素(Thread、ThreadLocal、ThreadLocalMap)之間的關(guān)系是值得我們引起注意的。
**************** 補(bǔ)疑完畢 ***************************
可見(jiàn),要正確使用ThreadLocal,必須注意以下幾點(diǎn):
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
1. 總是對(duì)ThreadLocal中的initialValue()方法進(jìn)行覆蓋。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
2. 當(dāng)使用set()或get()方法時(shí)牢記這兩個(gè)方法是對(duì)當(dāng)前活動(dòng)線程中的ThreadLocalMap進(jìn)行操作,一定要認(rèn)清哪個(gè)是當(dāng)前活動(dòng)線程!
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
3. 適當(dāng)?shù)氖褂梅盒停梢詼p少不必要的類型轉(zhuǎn)換以及可能由此產(chǎn)生的問(wèn)題。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
運(yùn)行該程序,我們發(fā)現(xiàn):程序的執(zhí)行過(guò)程只需要5秒,而如果采用同步的方法,程序的執(zhí)行結(jié)果相同,但執(zhí)行時(shí)間需要15秒。以前是多個(gè)線程為了爭(zhēng)取一個(gè)資源,不得不在同步規(guī)則的制約下互相謙讓,浪費(fèi)了一些時(shí)間。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
現(xiàn)在,采用ThreadLocal機(jī)制以后,可用的資源多了,你有我有全都有,所以,每個(gè)線程都可以毫無(wú)顧忌的工作,自然就提高了并發(fā)性,線程安全也得以保證。
當(dāng)今很多流行的開(kāi)源框架也采用ThreadLocal機(jī)制來(lái)解決線程的并發(fā)問(wèn)題。比如大名鼎鼎的 Struts 2.x 和 Spring 等。
把ThreadLocal這樣的話題放在我們的同步機(jī)制探討中似乎顯得不是很合適。但是ThreadLocal的確為我們解決多線程的并發(fā)問(wèn)題帶來(lái)了全新的思路。它為每個(gè)線程創(chuàng)建一個(gè)獨(dú)立的資源副本,從而將多個(gè)線程中的數(shù)據(jù)隔離開(kāi)來(lái),避免了同步所產(chǎn)生的性能問(wèn)題,是一種“以空間換時(shí)間”的解決方案。
但這并不是說(shuō)ThreadLocal就是包治百病的萬(wàn)能藥了。如果實(shí)際的情況不允許我們?yōu)槊總€(gè)線程分配一個(gè)本地資源副本的話,同步還是非常有意義的。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
好了,本系列到此馬上就要?jiǎng)澤弦粋€(gè)圓滿的句號(hào)了。不知大家有什么意見(jiàn)和疑問(wèn)沒(méi)有。希望看到你們的留言。
下一講中我們就來(lái)對(duì)之前的內(nèi)容進(jìn)行一個(gè)總結(jié),順便討論一下被遺忘的volatile關(guān)鍵字。敬請(qǐng)期待。
發(fā)表于 2010-04-24 13:36
X-Spirit
閱讀(8411)
評(píng)論(15)
編輯
收藏
所屬分類:
Java SE
評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
"總是對(duì)ThreadLocal中的initialValue()方法進(jìn)行覆蓋" ThreadLocal貌似不是這么用的,你現(xiàn)在為每個(gè)線程都 new 一個(gè)對(duì)象當(dāng)然不會(huì)沖突,干脆在 ThreadDemo3 的構(gòu)造方法中 new 好了,使用 ThreadLocal 干嘛?
pwl2014
評(píng)論于 2010-04-08 09:53
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
@pwl2014
這只是一個(gè)DEMO,使用new在這里其實(shí)就是一個(gè)打比方的方法。如果我用StudentFactory也許更容易接受一點(diǎn),呵呵。
在實(shí)際的應(yīng)用中,我們經(jīng)常可以看到一些用ThreadLocal來(lái)封裝資源的例子。他們無(wú)一例外的都是做一件事情:創(chuàng)建新的資源,供線程使用。例如用ThreadLocal來(lái)處理JDBC 的Connection。即使你沒(méi)有覆蓋initialValue()方法,而是用先get再判空,再set的方式,也還是為一個(gè)沒(méi)有獲取到connection的線程創(chuàng)建一個(gè)connection。
所以,問(wèn)題的關(guān)鍵不在于ThreadLocal使用的時(shí)候采用何種形式。ThreadLocal的思想精髓就是為每個(gè)線程創(chuàng)建獨(dú)立的資源副本。而使用ThreadLocal的時(shí)候最最重要的就是分清楚當(dāng)前活動(dòng)線程是哪個(gè)。
至于覆蓋initialValue()方法的問(wèn)題,這個(gè)應(yīng)該是仁者見(jiàn)仁,智者見(jiàn)智的問(wèn)題,我只是提出一個(gè)能夠節(jié)約代碼量的方案。一般情況下,覆蓋initialValue()方法已經(jīng)可以解決問(wèn)題,這是一種最為經(jīng)濟(jì)的編碼習(xí)慣,它不僅能夠達(dá)到要求,并且和JDK的原生API結(jié)合的很好,不容易出錯(cuò),當(dāng)然如果你需要在用ThreadLocal處理資源之前做一些其他的處理,那就另當(dāng)別論了。
X-Spirit
評(píng)論于 2010-04-08 11:07
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
嗯,不錯(cuò)!這一系列文章好。。。
anniezheng
評(píng)論于 2010-04-08 19:14
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
@anniezheng
謝謝夸獎(jiǎng)啦
X-Spirit
評(píng)論于 2010-04-09 00:09
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
@X-Spirit
這句話說(shuō)的好,ThreadLocal的思想精髓就是為每個(gè)線程創(chuàng)建獨(dú)立的資源副本。你這個(gè)Demo根本沒(méi)體現(xiàn)出來(lái),每個(gè)線程里都有一個(gè)ThreadLocal對(duì)象;應(yīng)該是一個(gè)ThreadLocal對(duì)象對(duì)應(yīng)多個(gè)線程,你這變成了一對(duì)一,完全沒(méi)體現(xiàn)出ThreadLocal的作用。
路過(guò)
評(píng)論于 2010-04-23 13:42
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
學(xué)習(xí)了!
boiledwater
評(píng)論于 2010-05-18 18:18
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
最近在網(wǎng)上看些關(guān)于線程的東西,開(kāi)始在一個(gè)論壇上找到轉(zhuǎn)載你的一片帖子,然后一路殺過(guò)來(lái),找到了你的大本營(yíng),一口氣看了你寫(xiě)這個(gè)6篇文章,感覺(jué)收獲挺大的,我之前學(xué)習(xí)了struts2,也發(fā)現(xiàn)了它用這個(gè)東西,一直沒(méi)有深究,在這里看到,覺(jué)得一下子發(fā)現(xiàn)了另一座山似的。但是我的疑問(wèn)是ThreadLocal這個(gè)東西的使用場(chǎng)景,還是不太明確。
康博
評(píng)論于 2010-05-28 14:11
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
@康博
感謝你的關(guān)注。關(guān)于應(yīng)用場(chǎng)景的問(wèn)題,我想沒(méi)有什么非常好的例子可以給你。不過(guò)只能告訴你使用ThreadLocal的好處就是可以避免同步帶來(lái)的性能損耗,并且,當(dāng)多個(gè)線程同時(shí)使用同一個(gè)類的實(shí)例的時(shí)候,如果這個(gè)實(shí)例不是單例模式的一個(gè)實(shí)現(xiàn),那么ThreadLocal就是值得考慮的。
X-Spirit
評(píng)論于 2010-06-07 00:54
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
@X-Spirit
謝謝你的回復(fù),期待你的下一篇文章。
康博
評(píng)論于 2010-06-12 15:23
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
@康博
呵呵,這個(gè)系列基本上要結(jié)束了。但是由于我最近比較忙,所以本系列的總結(jié)還沒(méi)有時(shí)間整理。不過(guò)過(guò)些日子會(huì)整理出來(lái)的。請(qǐng)保持關(guān)注。
X-Spirit
評(píng)論于 2010-06-12 19:55
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
支持技術(shù)貼,軟件也不錯(cuò)
圣光永恒
評(píng)論于 2010-07-07 18:23
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
技術(shù)的確的支持,頂一下
朱少
評(píng)論于 2010-07-08 16:37
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
好全啊
謝謝樓主
nauxiaoyao
評(píng)論于 2010-07-13 19:19
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
好詳細(xì)
了解了鎮(zhèn)面貌了
nauxiaoyao
評(píng)論于 2010-07-13 19:39
回復(fù)
更多評(píng)論
#
re: Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
不錯(cuò)的編程 支持技術(shù)帖
朱少
評(píng)論于 2010-07-17 12:44
回復(fù)
更多評(píng)論
新用戶注冊(cè)
刷新評(píng)論列表
只有注冊(cè)用戶
登錄
后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航:
博客園
IT新聞
Chat2DB
C++博客
博問(wèn)
管理
相關(guān)文章:
【Tech Details】【轉(zhuǎn)】有關(guān)Java SPI機(jī)制
【Effective】Logging最佳實(shí)踐
Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】
Java 多線程同步問(wèn)題的探究(四、協(xié)作,互斥下的協(xié)作——Java多線程協(xié)作(wait、notify、notifyAll))
Java 多線程同步問(wèn)題的探究(三、Lock來(lái)了,大家都讓開(kāi)【2. Fair or Unfair? It is a question...】)
Java 多線程同步問(wèn)題的探究(三、Lock來(lái)了,大家都讓開(kāi)【1. 認(rèn)識(shí)重入鎖】)
Java 多線程同步問(wèn)題的探究(二、給我一把鎖,我能創(chuàng)造一個(gè)規(guī)矩)
Java多線程同步問(wèn)題的探究(一、線程的先來(lái)后到)
【Effective】JVM 調(diào)優(yōu)參數(shù)說(shuō)明
<
2010年6月
>
日
一
二
三
四
五
六
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
常用鏈接
我的隨筆
我的文章
我的評(píng)論
我的參與
最新評(píng)論
留言簿
(6)
給我留言
查看公開(kāi)留言
查看私人留言
隨筆分類
(28)
Big Data
(rss)
Cloud
(rss)
Java EE
(rss)
Java FX
(rss)
Java SE(9)
(rss)
Java 輕量級(jí)企業(yè)開(kāi)發(fā)(5)
(rss)
Linux(3)
(rss)
MySQL
(rss)
NetBeans(1)
(rss)
Node.js
(rss)
NoSQL
(rss)
Oracle(3)
(rss)
前端技術(shù)
(rss)
開(kāi)源協(xié)議(1)
(rss)
思維模式
(rss)
悟(1)
(rss)
技術(shù)之外(5)
(rss)
敏捷開(kāi)發(fā)
(rss)
時(shí)間管理
(rss)
隨筆檔案
(90)
2014年9月 (1)
2014年3月 (1)
2014年2月 (1)
2014年1月 (1)
2013年2月 (1)
2012年11月 (1)
2012年10月 (1)
2012年3月 (1)
2012年2月 (1)
2011年2月 (1)
2010年4月 (6)
2010年3月 (4)
2010年1月 (2)
2009年11月 (1)
2009年8月 (1)
2009年7月 (1)
2009年6月 (2)
2009年5月 (1)
2009年4月 (13)
2009年3月 (1)
2009年2月 (1)
2009年1月 (2)
2008年12月 (3)
2008年11月 (1)
2008年10月 (1)
2008年9月 (3)
2008年5月 (1)
2008年4月 (9)
2008年3月 (3)
2008年1月 (1)
2007年12月 (4)
2007年10月 (2)
2007年9月 (6)
2007年8月 (9)
2007年7月 (1)
2007年4月 (1)
文章分類
(1)
My Voice(1)
(rss)
文章檔案
(1)
2009年12月 (1)
收藏夾
(4)
別人的學(xué)習(xí)筆記(4)
(rss)
牛人牛博
DaoRu的Blog
(rss)
愛(ài)折騰的道儒
Doug Lea's Home Page
Doug Lea's Home Page
jolestar
老王的博客
Tim Yang
(rss)
后端技術(shù)
Yang_net
(rss)
靠譜IT帥哥
搖擺巴赫@blog.sina
源碼控
搖擺巴赫@javaeye
源碼控
文初的一畝三分地
淘寶放翁
淘寶核心團(tuán)隊(duì)
淘寶核心團(tuán)隊(duì)
福林雨
(rss)
福林的博客
那誰(shuí)的BLOG
那誰(shuí)的BLOG
酷站
ImportNew
學(xué)習(xí)新知、發(fā)現(xiàn)新朋友
InfoQ中文站
InfoQ中文站
InfoQ英文站
InfoQ英文站
Java Code Geeks
A website for Java Geeks
并發(fā)編程網(wǎng)
并發(fā)編程網(wǎng)
開(kāi)源中國(guó)
OSCHINA
百度技術(shù)沙龍
百度技術(shù)沙龍
酷殼
(rss)
酷殼
最新隨筆
1.?【Math's History】什么是羅素悖論
2.?【Effective】IntelliJ IDEA MAC IDE config files
3.?5 Ways To Burn Out Programming
4.?【Efficiency】快速配置ubuntu桌面環(huán)境之Java環(huán)境配置[全軟件源安裝]
5.?【Efficiency】MAC下使用設(shè)定可以從mission control中啟動(dòng)的eclipse.app。
6.?【Effective】如何遷移git倉(cāng)庫(kù)
7.?【轉(zhuǎn)】閱讀我們的學(xué)科——計(jì)算機(jī)專業(yè)學(xué)習(xí)淺談
8.?【Tech Details】【轉(zhuǎn)】有關(guān)Java SPI機(jī)制
9.?【Efficiency】 監(jiān)控 Linux 性能的 18 個(gè)命令行工具
10.?【Effective】Logging最佳實(shí)踐
搜索
最新評(píng)論
1.?re: Java 多線程同步問(wèn)題的探究(三、Lock來(lái)了,大家都讓開(kāi)【1. 認(rèn)識(shí)重入鎖】)
上班
--地點(diǎn)
2.?re: 【轉(zhuǎn)】閱讀我們的學(xué)科——計(jì)算機(jī)專業(yè)學(xué)習(xí)淺談
好文!
--何楊
3.?re: [導(dǎo)入][轉(zhuǎn)]重復(fù)提交、重復(fù)刷新、防止后退的問(wèn)題以及處理方式
是多少
--乒乓、
4.?......
....
--..
5.?re: Java多線程同步問(wèn)題的探究(一、線程的先來(lái)后到)
多線程這塊一直是軟肋,學(xué)習(xí)一下,呵呵
--FlyingFish
閱讀排行榜
1.?Java 多線程同步問(wèn)題的探究(三、Lock來(lái)了,大家都讓開(kāi)【1. 認(rèn)識(shí)重入鎖】)(9054)
2.?Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】(8411)
3.?Java 多線程同步問(wèn)題的探究(二、給我一把鎖,我能創(chuàng)造一個(gè)規(guī)矩)(7440)
4.?Java 多線程同步問(wèn)題的探究(四、協(xié)作,互斥下的協(xié)作——Java多線程協(xié)作(wait、notify、notifyAll))(7252)
5.?Java多線程同步問(wèn)題的探究(一、線程的先來(lái)后到)(7103)
評(píng)論排行榜
1.?Java 多線程同步問(wèn)題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補(bǔ)疑】(15)
2.?Java 多線程同步問(wèn)題的探究(三、Lock來(lái)了,大家都讓開(kāi)【1. 認(rèn)識(shí)重入鎖】)(10)
3.?Java 多線程同步問(wèn)題的探究(二、給我一把鎖,我能創(chuàng)造一個(gè)規(guī)矩)(9)
4.?Java 多線程同步問(wèn)題的探究(四、協(xié)作,互斥下的協(xié)作——Java多線程協(xié)作(wait、notify、notifyAll))(9)
5.?Java多線程同步問(wèn)題的探究(一、線程的先來(lái)后到)(8)
Powered by:
博客園
模板提供:
滬江博客
Copyright ©2025 X-Spirit
主站蜘蛛池模板:
免费国产成人午夜在线观看
|
免费观看激色视频网站bd
|
免费看片在线观看
|
日韩一级免费视频
|
亚洲第一福利视频
|
亚洲乱妇熟女爽到高潮的片
|
花蝴蝶免费视频在线观看高清版
|
成年人在线免费看视频
|
国外亚洲成AV人片在线观看
|
国产99在线|亚洲
|
a级毛片黄免费a级毛片
|
成人免费在线观看网站
|
亚洲欧洲成人精品香蕉网
|
亚洲色大成网站WWW国产
|
A片在线免费观看
|
在线观看免费亚洲
|
亚洲AV无码欧洲AV无码网站
|
亚洲Av永久无码精品黑人
|
亚洲日本韩国在线
|
激情综合亚洲色婷婷五月
|
一级女人18片毛片免费视频
|
亚洲高清中文字幕免费
|
亚洲国产精品国自产拍AV
|
风间由美在线亚洲一区
|
四虎1515hh永久久免费
|
国产亚洲精品无码成人
|
理论亚洲区美一区二区三区
|
国产精品爱啪在线线免费观看
|
亚洲人成网亚洲欧洲无码久久
|
另类专区另类专区亚洲
|
AV免费网址在线观看
|
亚洲人成在线影院
|
国产免费一级高清淫曰本片
|
国产三级免费观看
|
亚洲国产av高清无码
|
国产精品免费高清在线观看
|
亚洲一区二区三区在线视频
|
性色av极品无码专区亚洲
|
免费无码AV电影在线观看
|
亚洲色图.com
|
久热免费在线视频
|