在實際業務中,由其是多執行緒並開業務中,經常會遇到某個執行緒執行超時。而程式如果不捕獲這類情況,就會導致程式一直處於等待狀態,從而影響後續執行緒的執行。
比如說網路通迅、單任務下的複雜資料庫查詢等,通常處理這類問題,可以啟用一個後臺守護執行緒來監控使用者執行緒(業務執行緒)的執行是否超時,如果超時就不在等待,這種做法,通常是在呼叫使用者執行緒的.start()方法之前,呼叫守護執行緒的start()方法,同時將超時時長傳給守護執行緒。在守護執行緒的run()方法,執行sleep()方法,休眠時間為超時時長,守護執行緒中有一個同步後的變數用於儲存使用者執行緒是否超時。而在使用者執行緒中,在程式執行完之後,再呼叫守掮執行緒改變同步變數。當守護執行緒sleep()方法之後,去有判斷同步變數的值是否已改變,如果沒有改變,說明使用者執行緒還未掃行完畢,也就是超時。但這種方法,不能中斷使用者執行緒。
除此之外,還有一種方法,可以中斷使用者執行緒不在繼續執行,採用Java.util.concurrent下面的介面、類也可以完成。以下是例子。
package com.test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class TimeOut { public static void main(String[] args){ int timeout = 2; //秒. ExecutorService executor = Executors.newSingleThreadExecutor(); Boolean result = false; Future<Boolean> future = executor.submit(new MyJob("請求引數"));// 將任務提交到執行緒池中 try { result = future.get(timeout*1000, TimeUnit.MILLISECONDS);// 設定在2秒的時間內完成 System.out.println(result); } catch (InterruptedException e) { System.out.println("執行緒中斷出錯。"); future.cancel(true);// 中斷執行此任務的執行緒 } catch (ExecutionException e) { System.out.println("執行緒服務出錯。"); future.cancel(true);// 中斷執行此任務的執行緒 } catch (TimeoutException e) {// 超時異常 System.out.println("超時。"); future.cancel(true);// 中斷執行此任務的執行緒 }finally{ System.out.println("執行緒服務關閉。"); executor.shutdown(); } } static class MyJob implements Callable<Boolean> { private String t; public MyJob(String temp){ this.t= temp; } public Boolean call() throws InterruptedException { for(int i=0;i<100;i++){ if(i==99){ System.out.println(t); } Thread.sleep(3000); if (Thread.interrupted()){ //很重要 return false; } } System.out.println("繼續執行.........."); return true; } } }