方法一
本例子使用ExecutorService 替代Timer來控制一個線程的逾時。代碼如下:
| 代碼如下 |
複製代碼 |
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable; 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 Test { public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(new Task()); try { System.out.println("Started.."); System.out.println(future.get(3, TimeUnit.SECONDS)); System.out.println("Finished!"); } catch (TimeoutException e) { System.out.println("Terminated!"); } executor.shutdownNow(); } } class Task implements Callable { @Override public String call() throws Exception { Thread.sleep(4000); // www.111cn.net Just to demo a long running task of 4 seconds. return "Ready!"; } } 將上面的 System.out.println(future.get(3, TimeUnit.SECONDS)); 改為 System.out.println(future.get(5, TimeUnit.SECONDS)); 線程將能正確執行完 You can intercept the timeout in the catch (TimeoutException e) block. |
方法二
類1:守護線程類
| 代碼如下 |
複製代碼 |
/** * 本線程設定了一個逾時時間 * 該線程開始運行後,經過指定逾時時間, * 該線程會拋出一個未檢查異常通知調用該線程的程式逾時 * 在逾時結束前可以調用該類的cancel方法取消計時 * @author solonote */ public class TimeoutThread extends Thread{ /** * 計時器逾時時間 */ private long timeout; /** * 計時是否被取消 */ private boolean isCanceled = false; /** * 當計時器逾時時拋出的異常 */ private TimeoutException timeoutException; /** * 構造器 * @param timeout 指定逾時的時間 */ public TimeoutThread(long timeout,TimeoutException timeoutErr) { super(); this.timeout = timeout; this.timeoutException = timeoutErr; //設定本線程為守護線程 this.setDaemon(true); } /** * 取消計時 */ public synchronized void cancel() { isCanceled = true; } /** * 啟動逾時計時器 */ public void run() { try { Thread.sleep(timeout); if(!isCanceled) throw timeoutException; } catch (InterruptedException e) { e.printStackTrace(); } } } 注: 類一中的TimeoutException是下邊的使用者自訂類,不是java中的java.util.concurrent.TimeoutException 類2.拋出異常類,該類繼承了RuntimeException,原因是run方法不能拋出已檢測異常。 public class TimeoutException extends RuntimeException { /** * 序列化號 */ private static final long serialVersionUID = -8078853655388692688L; public TimeoutException(String errMessage) { super(errMessage); } } 使用方法: //初始化逾時類 TimeoutThread t = new TimeoutThread(5000,new TimeoutException("逾時")); try{ t.start(); .....要檢測逾時的程式段.... t.cancel(); }catch (TimeoutException e) { ...對逾時的處理... } TimeoutException可以更換為其他未檢查異常類。 |
方法說明:
本方法的使用可以實現線程自己管理逾時,並且可以管理某一段代碼逾時時,可以在方法內部給出處理辦法。
但是需要注意的是:本方法的逾時時間並不是當前線程的已耗用時間,而是計時器開始計時起系統啟動並執行時間。