java中的超时方法

在java类中,我有一个有时需要很长时间才能执行的方法。 也许它挂在那个方法流程中。 我想要的是如果方法没有在特定时间内完成,程序应退出该方法并继续其余的流程。

请告诉我有没有办法处理这种情况。

您必须使用线程才能实现此目的。 线程没有害处:)下面的例子运行一段代码10秒然后结束它。

public class Test { public static void main(String args[]) throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("0"); method(); } }); thread.start(); long endTimeMillis = System.currentTimeMillis() + 10000; while (thread.isAlive()) { if (System.currentTimeMillis() > endTimeMillis) { System.out.println("1"); break; } try { System.out.println("2"); Thread.sleep(500); } catch (InterruptedException t) {} } } static void method() { long endTimeMillis = System.currentTimeMillis() + 10000; while (true) { // method logic System.out.println("3"); if (System.currentTimeMillis() > endTimeMillis) { // do some clean-up System.out.println("4"); return; } } } } 

在不同的线程中执行该方法,您可以随时结束一个线程。

基于上面的snipplet,我尝试创造一个美化的春豆。

这样的执行在有限的runtimeInMs中运行传递的limitedRuntimeTask 。 如果任务在其时间限制内完成,则调用者将继续正常执行。

如果limitedRuntimeTask未能在定义的runtimeInMs中完成,则调用者将接收回执行的线程。 如果定义了timeBreachedTask,它将在返回调用者之前执行。

 public class LimitedRuntimeExecutorImpl { public void runTaskInLessThanGivenMs(int runtimeInMs, final Callable limitedRuntimeTask, final Callable timeBreachedTask) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { LOGGER.info("Started limitedRuntimeTask"); limitedRuntimeTask.call(); LOGGER.info("Finished limitedRuntimeTask in time"); } catch (Exception e) { LOGGER.error("LimitedRuntimeTask exception", e); } } }); thread.start(); long endTimeMillis = System.currentTimeMillis() + runtimeInMs; while (thread.isAlive()) { if (System.currentTimeMillis() > endTimeMillis) { LOGGER.warn("LmitedRuntimeTask did not finish in time (" + runtimeInMs + ")ms. It will run in vain."); if(timeBreachedTask != null ){ try { LOGGER.info("Executing timeBreachedTask"); timeBreachedTask.call(); LOGGER.info("Finished timeBreachedTask"); } catch (Exception e) { LOGGER.error("timeBreachedTask exception", e); } } return; } try { Thread.sleep(10); } catch (InterruptedException t) {} } } 

}

我觉得接受答案的方法有点过时了。 使用Java8,它可以更简单地完成。

说,你有一个方法

 MyResult conjureResult(String param) throws MyException { ... } 

然后你可以这样做(继续阅读,这只是为了显示方法):

 private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor(); MyResult conjureResultWithTimeout(String param, int timeoutMs) throws Exception { Future future = timeoutExecutorService.submit(() -> conjureResult(param)); return future.get(timeoutMs, TimeUnit.MILLISECONDS); } 

当然,抛出exception是坏的,这是正确的扩展版本,并且有正确的error handling,但我建议你仔细检查它,你可能想要做一些不同的事情(记录,在扩展结果中返回超时等):

 private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor(); MyResult conjureResultWithTimeout(String param, int timeoutMs) throws MyException { Future future = timeoutExecutorService.submit(() -> conjureResult(param)); try { return future.get(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { //something interrupted, probably your service is shutting down Thread.currentThread().interrupt(); throw new RuntimeException(e); } catch (ExecutionException e) { //error happened while executing conjureResult() - handle it if (e.getCause() instanceof MyException) { throw (MyException)e.getCause(); } else { throw new RuntimeException(e); } } catch (TimeoutException e) { //timeout expired, you may want to do something else here throw new RuntimeException(e); } }