項目背景
1、Android項目;
2、依賴httpclient請求中的異步傳回資料;
2、countDownLatch用來構造一個同步場景,傳回httpclient請求的response資料,await逾時時間10s;
3、線程池數量:4;
問題現象
在網絡比較慢的場景下,多次在前端觸發該業務流程,大機率出現每一次的click事件,都會觸發線程countDownLatch.await的10s逾時;
關鍵詞
多線程、countDownLatch、線程池耗盡、逾時
定位過程
通過增加日志可發現,httpclient的接口耗時遠遠低于10s的逾時時間,調用httpclient前列印入口日志,均正常列印調用,接口均正常傳回,且耗時較短,則判斷該逾時并非服務端問題;
列印日志大約時間如下:
先列印4條調用httpclient的日志,然後過10s列印await逾時日志,之後再列印接口請求回調日志,判斷是回調過慢導緻await逾時;
猜測:由于線程池數量有限,await操作阻塞目前線程,導緻回調方法無法搶占到線程,最終造成逾時;
CountDownLatch原理
概念:這個類使一個線程,等其他線程執行完畢後再執行;是通過計數器來實作的,對象初始化時設定一個int值為需要等到的線程數量,一個等待線程執行完畢後 -1,等數量歸零後,在閉鎖上等待的線程就可以繼續執行了。
源碼:
// count為計數值
public CountDownLatch(int count){}
//調用await()方法的線程會被挂起,它會等待直到count值為0才繼續執行
public void await() throws InterruptedException { };
//和await()類似,隻不過等待一定的時間後count值還沒變為0的話就會繼續執行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//将count值減1
public void countDown() { };
常見使用常見:用于進行接口時間優化,将串行流程分割成并行場景,減少調用時間;
什麼是閉鎖??
閉鎖——是一種Synchronizer對象,它根據本身的狀态調節線程的控制流,常見的Synchronizer包括信号量、關卡、閉鎖。
AQS
https://www.jianshu.com/p/0f876ead2846