日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中如何实现线程的超时中断

發布時間:2023/12/3 java 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中如何实现线程的超时中断 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??Java中如何實現線程的超時中斷

背景

之前在實現熔斷降級組件的時候,需要實現接口請求的超時中斷。意思是,業務在使用熔斷降級功能時,在平臺上設置了一個超時時間,如果請求進入熔斷器開始計時,接口在超時時間內沒有響應,則需要提早中斷該請求并返回。

比如正常下游接口的超時時間為800ms,但是因為自身業務的特殊需求,最多只能等200ms,如果指定之內沒有數據返回,則返回降級數據。這里處理請求的線程可以看成是tomcat線程池中的一個線程,如果通過線程池返回的Future,可以很輕松的實現超時中斷返回,但是當前情況下,并不能拿到Futrue,又不想額外引入一個線程池,所以需要另外一種實現思路。

思路

中斷一個線程的思路有哪些? 除了已經廢棄的Thread.stop, Thread.suspend, Thread.resume 方法,剩下的貌似只有一種方案了,就是調用當前線程的 interrupt(),但是這個方法的作用并不是中斷線程,而是設置一個標識,通知該線程可以被中斷了,到底是繼續執行,還是中斷返回,由線程本身自己決定。

具體來說,當對一個線程調用了 interrupt()之后,如果該線程處于被阻塞狀態(比如執行了wait、sleep或join等方法),那么會立即退出阻塞狀態,并拋出一個 InterruptedException異常,在代碼中catch這個異常進行后續處理。如果線程一直處于運行狀態,那么只會把該線程的中斷標志設置為 true,僅此而已,所以 interrupt()并不能真正的中斷線程,不過在rpc調用的場景中,請求線程一般都處于阻塞狀態,等待數據返回,這時 interrupt()方法是可以派上用場的。

那么,要實現指定超時時間內中斷請求線程,還有最后一個問題需要解決:什么時候,由誰去執行 interrupt()方法?

必然這個方法只能由其它線程來執行了(自己都阻塞了,執行個鬼),而且是在請求進入熔斷器時,并在超時時間之后執行,有點繞,比如超時時間是200ms,那么請求進入熔斷器之后,再過200ms,就執行 interrupt(),但是在200ms之內有數據返回,那么就不執行 interrupt()了。

實現

需求已經很明確了,相當于延遲執行一個task,其內部邏輯就是執行請求線程的 interrupt(),當然還有其它的邏輯。

Runnable task = new Runnable() {@Overridepublic void run() {try {thread.interrupt();// 取消定時器任務f.cancel();} catch (Exception e) {logger.error("Failed while ticking TimerListener", e);}} };

Doug Lea大神提供的 ScheduledThreadPoolExecutor可以很好的滿足這個需求,通過 scheduleAtFixedRate方法可以很方便的實現在延遲指定時間之后執行提交的任務。

?

ScheduledFuture<?> f = executor.scheduleAtFixedRate(task, timeout, timeout, TimeUnit.MILLISECONDS);

在請求進入熔斷器時,順便提交一個任務到線程池中等待執行,如果接口在超時時間內沒有返回,那么該任務會被觸發,并執行請求線程的 interrupt方法,這樣就實現了請求線程的中斷(因為這時請求線程正在被阻塞,等待數據返回),另外需要清空定時任務,不然這個任務會一直執行。

如果接口正常返回了,也要記得清空定時任務,并且在請求退出熔斷器的時候,記得恢復請求線程的中斷標識,如何恢復?在請求線程中執行下面代碼即可。

Thread.interrupted();// 內部邏輯 public static boolean interrupted() {return currentThread().isInterrupted(true); }// 參數為true,可以清除中斷標識 private native boolean isInterrupted(boolean ClearInterrupted);

執行當前線程(即請求線程)的isInterrupted方法。

使用這種方式實現請求的超時中斷,在QPS很高的情況下,會有額外的性能損失,因為每次請求都要提交一個任務到線程池中等待執行。

總結

以上是生活随笔為你收集整理的Java中如何实现线程的超时中断的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。