中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

3年java開發竟然還不知道Lambda的這個坑

發布時間:2020-08-10 02:36:08 來源:網絡 閱讀:540 作者:架構師追風 欄目:編程語言

背景

有朋友反饋zk連接很慢。整理出zk連接的關鍵邏輯如下:

3年java開發竟然還不知道Lambda的這個坑

上面的代碼造成第一次調用ClientZkAgent.getInstance的時候,需耗時10s, 這個時間恰好跟semaphore的超時時間相當. 在此期間,整個世界好像停滯了一樣。

分析

在本地重現后,通過jstack獲得系統停滯期間的線程棧,發現這個時候zookeeper的EventThread有個比較奇怪的現象:

3年java開發竟然還不知道Lambda的這個坑

客戶端實際上很快就連上了zookeeper并返回后生成了SyncConnected事件,而且EventThread已經在回調Watcher.process方法了,但似乎事件線程就一直hold在上面#_1的位置無法往下走, 同時,lambda表達式變成了ClientZkAgent的一個方法了:lambda$connect$0。

了解了一下Java中lambda的實現方式,事情水落石出了。

3年java開發竟然還不知道Lambda的這個坑

簡而言之,jvm會把lambda表達式轉換成所在類的一個方法lambda${method}${seq}(method為該lambda所在的方法名,例如上面的connect方法),同時通過動態代理生成一個代理類(該代理類實現了lambda表達式所代表的具體接口),在該代理類中調用lambda${method}${seq}。

在上面的例子中,生成的代理類大概如下:

3年java開發竟然還不知道Lambda的這個坑

再梳理一下:

業務線程:

1.通過靜態方法ClientZkAgent.getInstance()獲取實例,第一次訪問的時候會觸發類ClientZkAgent的裝載。

2.裝載過程中,裝載靜態成員instance,這時候會嘗試創建一個ClientZkAgent對象。

3.在ClientZkAgent的構造函數中連接zk,并通過CountdownLatch進入阻塞狀態。注意這時候類裝載還沒完成。

4.CountdownLatch超時后完成對象的初始化以及整個類的加載

zk事件線程:

SyncConnected事件觸發后,調用ClientZkAgent.lambda$connect$0(event), 試圖喚醒業務線程(喚醒邏輯在lambda中)。

然而這時候ClientZkAgent還沒加載完,事件線程只能等待類加載流程的結束。

業務線程加載完ClientZkAgent后,事件線程完成事件的處理。

可見,在這個過程中,兩個線程相互等待(類似死鎖但不是死鎖),直至業務線程超時后才化解這個局面。

歡迎大家關注我的公種浩【程序員追風】,文章都會在里面更新,整理的資料也會放在里面。

解決

修改ClientZkAgent的初始化邏輯如下:

3年java開發竟然還不知道Lambda的這個坑


最后

歡迎大家一起交流,喜歡文章記得點個贊,感謝支持!



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

瑞安市| 建水县| 灵石县| 衡东县| 石河子市| 繁昌县| 比如县| 连城县| 琼中| 汉寿县| 丽水市| 高安市| 泰安市| 北票市| 平果县| 安乡县| 阳原县| 靖宇县| 正安县| 定结县| 芜湖县| 庆安县| 泰和县| 读书| 海兴县| 广灵县| 苏尼特左旗| 凤城市| 万全县| 宜宾市| 新丰县| 遂宁市| 黄梅县| 洛阳市| 晋城| 九龙县| 阿鲁科尔沁旗| 南昌县| 嫩江县| 沭阳县| 崇信县|