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.jquerycn.cn 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可以更换为其他未检查异常类。 方法说明: 本方法的使用可以实现线程自己管理超时,并且可以管理某一段代码超时时,可以在方法内部给出处理办法。 但是需要注意的是:本方法的超时时间并不是当前线程的运行时间,而是计时器开始计时起系统运行的时间。 |
|