1. 程式人生 > >感悟:Java的多執行緒跟Java的類系統之間的關係

感悟:Java的多執行緒跟Java的類系統之間的關係

一直對Java將執行緒封裝成物件的技術不甚了了,昨天幫一個新員工定位rosjava使用問題,一開始以為是多執行緒問題,但多番嘗試未果後,走查程式碼,發現他在onClick函式裡new CustomRosNode並賦給nodeHandler引用,導致nodeHandler最早繫結的物件被GC,問題是CustomRosNode的建構函式並不能構建出一個全功能的node,還需要後續的初始化,但他在onClick只調用了建構函式,導致nodeHandler的publisher指標成了空指標,進而出錯。

但是這個空指標現象讓我首先懷疑Java的執行緒機制,於是走了很多彎路,找到真正的BUG後,我為了教育新員工,也為了回答自己內心的疑惑,在各種關鍵點列印執行緒ID,發現CustomRosNode有一部分確實執行在子執行緒(ros的loop),另一部分執行在主執行緒(建構函式以及其他非ros相關函式),為何這兩部分程式碼能訪問CustomRosNode的同一個資料成員?

晚上睡下後進一步想,為什麼執行緒a的程式碼可以訪問線上程b中例項化的物件c?答案是:所有Java物件是在【堆】上分配的,而堆是所有執行緒可見的,只要執行緒a握有c物件的引用r,則通過r呼叫c的方法x完全是可行的,只不過這樣一來,方法x就不是執行線上程b上,而是執行緒a上了!

其實,類(方法和資料)跟執行緒,一毛錢關係都沒有。可以這麼想象,一個倉庫(堆heap)裡有好多包裹(物件),包裹裡面有商品(資料資料),包裹上面有快遞單指示該怎麼寄送(方法成員),若干個快遞員(執行緒)負責將這些包裹寄出去,每個快遞員都可以寄任意一個包裹(堆內所有物件都共享同一個4GB程序地址空間),包裹x可以被快遞員a處理,也可以被快遞員b處理,但不能同時被二者處理(synchronized)

Java將所有物件放在堆上,簡化了記憶體管理,實現了執行緒類(-_-!引入了混淆),但增加了GC,孰優孰劣?看選擇吧

我選擇go die