X-Spirit
Always Beyond the Time
BlogJava
|
首頁
|
發(fā)新隨筆
|
發(fā)新文章
|
聯(lián)系
|
聚合
|
管理
隨筆:91 文章:1 評論:65 引用:0
Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
前面我們介紹了Java當中多個線程搶占一個共享資源的問題。但不論是同步還是重入鎖,都不能實實在在的解決資源緊缺的情況,這些方案只是靠制定規(guī)則來約束線程的行為,讓它們不再拼命的爭搶,而不是真正從實質(zhì)上解決他們對資源的需求。
在JDK 1.2當中,引入了java.lang.ThreadLocal。它為我們提供了一種全新的思路來解決線程并發(fā)的問題。但是他的名字難免讓我們望文生義:本地線程?
什么是本地線程?
本地線程開玩笑的說:不要迷戀哥,哥只是個傳說。
其實ThreadLocal并非Thread at Local,而是LocalVariable in a Thread。
根據(jù)WikiPedia上的介紹,ThreadLocal其實是源于一項多線程技術(shù),叫做Thread Local Storage,即線程本地存儲技術(shù)。不僅僅是Java,在C++、C#、.NET、Python、Ruby、Perl等開發(fā)平臺上,該技術(shù)都已經(jīng)得以實現(xiàn)。
當使用ThreadLocal維護變量時,它會為每個使用該變量的線程提供獨立的變量副本。也就是說,他從根本上解決的是資源數(shù)量的問題,從而使得每個線程持有相對獨立的資源。這樣,當多個線程進行工作的時候,它們不需要糾結(jié)于同步的問題,于是性能便大大提升。但資源的擴張帶來的是更多的空間消耗,ThreadLocal就是這樣一種利用空間來換取時間的解決方案。
說了這么多,來看看如何正確使用ThreadLocal。
通過研究JDK文檔,我們知道,ThreadLocal中有幾個重要的方法:get()、set()、remove()、initailValue(),對應的含義分別是:
返回此線程局部變量的當前線程副本中的值、將此線程局部變量的當前線程副本中的值設置為指定值、移除此線程局部變量當前線程的值、返回此線程局部變量的當前線程的“初始值”。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
還記得我們在第三篇的上半節(jié)引出的那個例子么?幾個線程修改同一個Student對象中的age屬性。為了保證這幾個線程能夠工作正常,我們需要對Student的對象進行同步。
下面我們對這個程序進行一點小小的改造,我們通過繼承Thread來實現(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/
貌似這個程序沒什么問題。但是運行結(jié)果卻顯示:這個程序中的3個線程會拋出3個空指針異常。讀者一定感到很困惑。我明明在構(gòu)造器當中把Student對象set進了ThreadLocal里面阿,為什么run起來之后居然在調(diào)用stuLocal.get()方法的時候得到的是NULL呢?
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
帶著這個疑問,讓我們深入到JDK的代碼當中,去一看究竟。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
原來,在ThreadLocal中,有一個內(nèi)部類叫做ThreadLocalMap。這個ThreadLocalMap并非java.util.Map的一個實現(xiàn),而是利用java.lang.ref.WeakReference實現(xiàn)的一個鍵-值對應的數(shù)據(jù)結(jié)構(gòu)其中,key是ThreadLocal類型,而value是Object類型,我們可以簡單的視為HashMap<ThreadLocal,Object>。
而在每一個Thread對象中,都有一個ThreadLocalMap的引用,即Thread.threadLocals。而ThreadLocal的set方法就是首先嘗試從當前線程中取得ThreadLocalMap(以下簡稱Map)對象。如果取到的不為null,則以ThreadLocal對象自身為key,來取Map中的value。如果取不到Map對象,則首先為當前線程創(chuàng)建一個ThreadLocalMap,然后以ThreadLocal對象自身為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方法則是首先得到當前線程的ThreadLocalMap對象,然后,根據(jù)ThreadLocal對象自身,取出相應的value。當然,如果在當前線程中取不到ThreadLocalMap對象,則嘗試為當前線程創(chuàng)建ThreadLocalMap對象,并以ThreadLocal對象自身為key,把initialValue()方法產(chǎn)生的對象作為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
;
}
這樣,我們就明白上面的問題出在哪里:我們在main方法執(zhí)行期間,試圖在調(diào)用ThreadDemo3的構(gòu)造器時向ThreadLocal置入Student對象,而此時,以ThreadLocal對象為key,Student對象為value的Map是被放入當前的活動線程內(nèi)的。也就是Main線程。而當我們的3個ThreadDemo3線程運行起來以后,調(diào)用get()方法,都是試圖從當前的活動線程中取得ThreadLocalMap對象,但當前的活動線程顯然已經(jīng)不是Main線程了,于是,程序最終執(zhí)行了ThreadLocal原生的initialValue()方法,返回了null。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
講到這里,我想不少朋友一定已經(jīng)看出來了:ThreadLocal的initialValue()方法是需要被覆蓋的。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
于是,ThreadLocal的正確使用方法是:將ThreadLocal以內(nè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());
}
}
********** 補疑 ******************
有的童鞋可能會問:“你這個Demo根本沒體現(xiàn)出來,每個線程里都有一個ThreadLocal對象;應該是一個ThreadLocal對象對應多個線程,你這變成了一對一,完全沒體現(xiàn)出ThreadLocal的作用。”
那么我們來看一下如何用一個ThreadLocal對象來對應多個線程:
/** */
/**
*
*
@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());
}
}
這里,多個線程對象都使用同一個實現(xiàn)了Runnable接口的ThreadDemo3對象來構(gòu)造。這樣,多個線程使用的ThreadLocal對象就是同一個。結(jié)果仍然是正確的。但是仔細回想一下,這兩種實現(xiàn)方案有什么不同呢?
答案其實很簡單,并沒有本質(zhì)上的不同。對于第一種實現(xiàn),不同的線程對象當中ThreadLocalMap里面的KEY使用的是不同的ThreadLocal對象。而對于第二種實現(xiàn),不同的線程對象當中ThreadLocalMap里面的KEY是同一個ThreadLocal對象。但是從本質(zhì)上講,不同的線程對象都是利用其自身的ThreadLocalMap對象來對各自的Student對象進行封裝,用ThreadLocal對象作為該ThreadLocalMap的KEY。所以說,“ThreadLocal的思想精髓就是為每個線程創(chuàng)建獨立的資源副本。”這句話并不應當被理解成:一定要使用同一個ThreadLocal對象來對多個線程進行處理。因為真正用來封裝變量的不是ThreadLocal。就算是你的程序中所有線程都共用同一個ThreadLocal對象,而你真正封裝到ThreadLocalMap中去的仍然是.hashCode()方法返回不同值的不同對象。就好比線程就是房東,ThreadLocalMap就是房東的房子。房東通過ThreadLocal這個中介去和房子里的房客打交道,而房東不管要讓房客住進去還是搬出來,都首先要經(jīng)過ThreadLocal這個中介。
所以提到ThreadLocal,我們不應當顧名思義的認為JDK里面提供ThreadLocal就是提供了一個用來封裝本地線程存儲的容器,它本身并沒有Map那樣的容器功能。真正發(fā)揮作用的是ThreadLocalMap。也就是說,事實上,采用ThreadLocal來提高并發(fā)行,首先要理解,這不是一種簡單的對象封裝,而是一套機制,而這套機制中的三個關(guān)鍵因素(Thread、ThreadLocal、ThreadLocalMap)之間的關(guān)系是值得我們引起注意的。
**************** 補疑完畢 ***************************
可見,要正確使用ThreadLocal,必須注意以下幾點:
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
1. 總是對ThreadLocal中的initialValue()方法進行覆蓋。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
2. 當使用set()或get()方法時牢記這兩個方法是對當前活動線程中的ThreadLocalMap進行操作,一定要認清哪個是當前活動線程!
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
3. 適當?shù)氖褂梅盒?,可以減少不必要的類型轉(zhuǎn)換以及可能由此產(chǎn)生的問題。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
運行該程序,我們發(fā)現(xiàn):程序的執(zhí)行過程只需要5秒,而如果采用同步的方法,程序的執(zhí)行結(jié)果相同,但執(zhí)行時間需要15秒。以前是多個線程為了爭取一個資源,不得不在同步規(guī)則的制約下互相謙讓,浪費了一些時間。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
現(xiàn)在,采用ThreadLocal機制以后,可用的資源多了,你有我有全都有,所以,每個線程都可以毫無顧忌的工作,自然就提高了并發(fā)性,線程安全也得以保證。
當今很多流行的開源框架也采用ThreadLocal機制來解決線程的并發(fā)問題。比如大名鼎鼎的 Struts 2.x 和 Spring 等。
把ThreadLocal這樣的話題放在我們的同步機制探討中似乎顯得不是很合適。但是ThreadLocal的確為我們解決多線程的并發(fā)問題帶來了全新的思路。它為每個線程創(chuàng)建一個獨立的資源副本,從而將多個線程中的數(shù)據(jù)隔離開來,避免了同步所產(chǎn)生的性能問題,是一種“以空間換時間”的解決方案。
但這并不是說ThreadLocal就是包治百病的萬能藥了。如果實際的情況不允許我們?yōu)槊總€線程分配一個本地資源副本的話,同步還是非常有意義的。
轉(zhuǎn)載注明出處:http://x- spirit.javaeye.com/、http: //www.tkk7.com/zhangwei217245/
好了,本系列到此馬上就要劃上一個圓滿的句號了。不知大家有什么意見和疑問沒有。希望看到你們的留言。
下一講中我們就來對之前的內(nèi)容進行一個總結(jié),順便討論一下被遺忘的volatile關(guān)鍵字。敬請期待。
發(fā)表于 2010-04-24 13:36
X-Spirit
閱讀(8411)
評論(15)
編輯
收藏
所屬分類:
Java SE
評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
"總是對ThreadLocal中的initialValue()方法進行覆蓋" ThreadLocal貌似不是這么用的,你現(xiàn)在為每個線程都 new 一個對象當然不會沖突,干脆在 ThreadDemo3 的構(gòu)造方法中 new 好了,使用 ThreadLocal 干嘛?
pwl2014
評論于 2010-04-08 09:53
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
@pwl2014
這只是一個DEMO,使用new在這里其實就是一個打比方的方法。如果我用StudentFactory也許更容易接受一點,呵呵。
在實際的應用中,我們經(jīng)??梢钥吹揭恍┯肨hreadLocal來封裝資源的例子。他們無一例外的都是做一件事情:創(chuàng)建新的資源,供線程使用。例如用ThreadLocal來處理JDBC 的Connection。即使你沒有覆蓋initialValue()方法,而是用先get再判空,再set的方式,也還是為一個沒有獲取到connection的線程創(chuàng)建一個connection。
所以,問題的關(guān)鍵不在于ThreadLocal使用的時候采用何種形式。ThreadLocal的思想精髓就是為每個線程創(chuàng)建獨立的資源副本。而使用ThreadLocal的時候最最重要的就是分清楚當前活動線程是哪個。
至于覆蓋initialValue()方法的問題,這個應該是仁者見仁,智者見智的問題,我只是提出一個能夠節(jié)約代碼量的方案。一般情況下,覆蓋initialValue()方法已經(jīng)可以解決問題,這是一種最為經(jīng)濟的編碼習慣,它不僅能夠達到要求,并且和JDK的原生API結(jié)合的很好,不容易出錯,當然如果你需要在用ThreadLocal處理資源之前做一些其他的處理,那就另當別論了。
X-Spirit
評論于 2010-04-08 11:07
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
嗯,不錯!這一系列文章好。。。
anniezheng
評論于 2010-04-08 19:14
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
@anniezheng
謝謝夸獎啦
X-Spirit
評論于 2010-04-09 00:09
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)
@X-Spirit
這句話說的好,ThreadLocal的思想精髓就是為每個線程創(chuàng)建獨立的資源副本。你這個Demo根本沒體現(xiàn)出來,每個線程里都有一個ThreadLocal對象;應該是一個ThreadLocal對象對應多個線程,你這變成了一對一,完全沒體現(xiàn)出ThreadLocal的作用。
路過
評論于 2010-04-23 13:42
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
學習了!
boiledwater
評論于 2010-05-18 18:18
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
最近在網(wǎng)上看些關(guān)于線程的東西,開始在一個論壇上找到轉(zhuǎn)載你的一片帖子,然后一路殺過來,找到了你的大本營,一口氣看了你寫這個6篇文章,感覺收獲挺大的,我之前學習了struts2,也發(fā)現(xiàn)了它用這個東西,一直沒有深究,在這里看到,覺得一下子發(fā)現(xiàn)了另一座山似的。但是我的疑問是ThreadLocal這個東西的使用場景,還是不太明確。
康博
評論于 2010-05-28 14:11
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
@康博
感謝你的關(guān)注。關(guān)于應用場景的問題,我想沒有什么非常好的例子可以給你。不過只能告訴你使用ThreadLocal的好處就是可以避免同步帶來的性能損耗,并且,當多個線程同時使用同一個類的實例的時候,如果這個實例不是單例模式的一個實現(xiàn),那么ThreadLocal就是值得考慮的。
X-Spirit
評論于 2010-06-07 00:54
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
@X-Spirit
謝謝你的回復,期待你的下一篇文章。
康博
評論于 2010-06-12 15:23
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
@康博
呵呵,這個系列基本上要結(jié)束了。但是由于我最近比較忙,所以本系列的總結(jié)還沒有時間整理。不過過些日子會整理出來的。請保持關(guān)注。
X-Spirit
評論于 2010-06-12 19:55
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
支持技術(shù)貼,軟件也不錯
圣光永恒
評論于 2010-07-07 18:23
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
技術(shù)的確的支持,頂一下
朱少
評論于 2010-07-08 16:37
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
好全啊
謝謝樓主
nauxiaoyao
評論于 2010-07-13 19:19
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
好詳細
了解了鎮(zhèn)面貌了
nauxiaoyao
評論于 2010-07-13 19:39
回復
更多評論
#
re: Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
不錯的編程 支持技術(shù)帖
朱少
評論于 2010-07-17 12:44
回復
更多評論
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發(fā)表評論。
網(wǎng)站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
相關(guān)文章:
【Tech Details】【轉(zhuǎn)】有關(guān)Java SPI機制
【Effective】Logging最佳實踐
Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】
Java 多線程同步問題的探究(四、協(xié)作,互斥下的協(xié)作——Java多線程協(xié)作(wait、notify、notifyAll))
Java 多線程同步問題的探究(三、Lock來了,大家都讓開【2. Fair or Unfair? It is a question...】)
Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)
Java 多線程同步問題的探究(二、給我一把鎖,我能創(chuàng)造一個規(guī)矩)
Java多線程同步問題的探究(一、線程的先來后到)
【Effective】JVM 調(diào)優(yōu)參數(shù)說明
<
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
常用鏈接
我的隨筆
我的文章
我的評論
我的參與
最新評論
留言簿
(6)
給我留言
查看公開留言
查看私人留言
隨筆分類
(28)
Big Data
(rss)
Cloud
(rss)
Java EE
(rss)
Java FX
(rss)
Java SE(9)
(rss)
Java 輕量級企業(yè)開發(fā)(5)
(rss)
Linux(3)
(rss)
MySQL
(rss)
NetBeans(1)
(rss)
Node.js
(rss)
NoSQL
(rss)
Oracle(3)
(rss)
前端技術(shù)
(rss)
開源協(xié)議(1)
(rss)
思維模式
(rss)
悟(1)
(rss)
技術(shù)之外(5)
(rss)
敏捷開發(fā)
(rss)
時間管理
(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)
別人的學習筆記(4)
(rss)
牛人牛博
DaoRu的Blog
(rss)
愛折騰的道儒
Doug Lea's Home Page
Doug Lea's Home Page
jolestar
老王的博客
Tim Yang
(rss)
后端技術(shù)
Yang_net
(rss)
靠譜IT帥哥
搖擺巴赫@blog.sina
源碼控
搖擺巴赫@javaeye
源碼控
文初的一畝三分地
淘寶放翁
淘寶核心團隊
淘寶核心團隊
福林雨
(rss)
福林的博客
那誰的BLOG
那誰的BLOG
酷站
ImportNew
學習新知、發(fā)現(xiàn)新朋友
InfoQ中文站
InfoQ中文站
InfoQ英文站
InfoQ英文站
Java Code Geeks
A website for Java Geeks
并發(fā)編程網(wǎng)
并發(fā)編程網(wǎng)
開源中國
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下使用設定可以從mission control中啟動的eclipse.app。
6.?【Effective】如何遷移git倉庫
7.?【轉(zhuǎn)】閱讀我們的學科——計算機專業(yè)學習淺談
8.?【Tech Details】【轉(zhuǎn)】有關(guān)Java SPI機制
9.?【Efficiency】 監(jiān)控 Linux 性能的 18 個命令行工具
10.?【Effective】Logging最佳實踐
搜索
最新評論
1.?re: Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)
上班
--地點
2.?re: 【轉(zhuǎn)】閱讀我們的學科——計算機專業(yè)學習淺談
好文!
--何楊
3.?re: [導入][轉(zhuǎn)]重復提交、重復刷新、防止后退的問題以及處理方式
是多少
--乒乓、
4.?......
....
--..
5.?re: Java多線程同步問題的探究(一、線程的先來后到)
多線程這塊一直是軟肋,學習一下,呵呵
--FlyingFish
閱讀排行榜
1.?Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)(9055)
2.?Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】(8411)
3.?Java 多線程同步問題的探究(二、給我一把鎖,我能創(chuàng)造一個規(guī)矩)(7441)
4.?Java 多線程同步問題的探究(四、協(xié)作,互斥下的協(xié)作——Java多線程協(xié)作(wait、notify、notifyAll))(7253)
5.?Java多線程同步問題的探究(一、線程的先來后到)(7104)
評論排行榜
1.?Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發(fā)安全性?)【更新重要補疑】(15)
2.?Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)(10)
3.?Java 多線程同步問題的探究(二、給我一把鎖,我能創(chuàng)造一個規(guī)矩)(9)
4.?Java 多線程同步問題的探究(四、協(xié)作,互斥下的協(xié)作——Java多線程協(xié)作(wait、notify、notifyAll))(9)
5.?Java多線程同步問題的探究(一、線程的先來后到)(8)
Powered by:
博客園
模板提供:
滬江博客
Copyright ©2025 X-Spirit
主站蜘蛛池模板:
精品国产香蕉伊思人在线在线亚洲一区二区
|
亚洲aⅴ无码专区在线观看春色
|
国产成人免费福利网站
|
久久免费观看国产99精品
|
一区二区三区AV高清免费波多
|
亚洲粉嫩美白在线
|
亚洲精品第五页中文字幕
|
亚洲人成精品久久久久
|
亚洲乱码日产精品a级毛片久久
|
99久久亚洲精品无码毛片
|
亚洲天堂中文字幕在线
|
精品国产免费观看一区
|
国产香蕉九九久久精品免费
|
四虎精品视频在线永久免费观看
|
精品免费视在线观看
|
美女巨胸喷奶水视频www免费
|
免费一区二区无码视频在线播放
|
亚洲精品国产av成拍色拍
|
久久亚洲精品专区蓝色区
|
亚洲国产视频网站
|
亚洲精品欧洲精品
|
久久久亚洲AV波多野结衣
|
亚洲黄色在线观看视频
|
久久久亚洲欧洲日产国码aⅴ
|
亚洲av中文无码乱人伦在线播放
|
亚洲女初尝黑人巨高清
|
亚洲国产成人精品无码区在线观看
|
婷婷综合缴情亚洲狠狠尤物
|
国产无遮挡裸体免费视频
|
亚洲午夜精品一区二区麻豆
|
亚洲AV无码一区二区三区在线
|
亚洲国产成人精品青青草原
|
亚洲视频欧洲视频
|
亚洲成年人免费网站
|
亚洲另类自拍丝袜第1页
|
亚洲va在线va天堂成人
|
亚洲色偷偷色噜噜狠狠99网
|
亚洲国产成人久久综合
|
青娱乐在线视频免费观看
|
免费一级毛片在线播放视频免费观看永久
|
日韩在线观看视频免费
|