在实际应用中,我们经常需要限定某些操作的执行时间,以避免程序运行过程中因为某些操作沉睡或者阻塞而导致程序失效。Java 提供了一种基于线程的等待机制,可以用来限定某些操作的执行时间。本文将介绍如何使用 Java 编写一个超时工具类
Java 编写超时工具类实例讲解
简介
在实际应用中,我们经常需要限定某些操作的执行时间,以避免程序运行过程中因为某些操作沉睡或者阻塞而导致程序失效。Java 提供了一种基于线程的等待机制,可以用来限定某些操作的执行时间。本文将介绍如何使用 Java 编写一个超时工具类来限定某个操作的最长执行时间。
实现方式
一个常用的方式是使用线程来控制等待时间,如下所示:
public class TimeoutUtils {
public static void runWithTimeout(Runnable runnable, long timeout) throws TimeoutException {
Thread thread = new Thread(() -> {
runnable.run();
});
thread.start();
try {
thread.join(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (thread.isAlive()) {
thread.interrupt();
throw new TimeoutException("Operation timed out after " + timeout + " milliseconds");
}
}
}
上述代码中,runWithTimeout
方法接收一个 Runnable
对象和一个超时时间,然后创建一个新线程并运行该 Runnable
对象,等待时间为超时时间。如果该线程在超时时间内完成了执行,那么程序正常运行。如果线程在超时时间内还没有完成执行,则中断线程并抛出一个 TimeoutException 异常。
上述代码主要通过线程的 join 方法来阻塞当前线程,等待新线程执行结束,如果新线程在指定时间内未能执行结束,那么就中断新线程并抛出 TimeoutException 异常。这种方式简单易行,适用于大量场景。一般来说,我们需要监控的是某个方法的执行时间,将其封装进 Runnable 对象中自然是一个好的选择。
示例
下面来看一下超时工具类的使用示例:
public class TimeoutUtilsDemo {
public static void main(String[] args) {
try {
TimeoutUtils.runWithTimeout(() -> {
// do something ...
// for example:
Thread.sleep(5000);
}, 2000);
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
上述代码中,TimeoutUtilsDemo
类中的 main
方法中,我们使用 TimeoutUtils
类的 runWithTimeout
方法来执行一段代码。该代码会模拟一个比较耗时的操作,即休眠 5 秒钟。在执行 runWithTimeout
方法时,我们设置了超时时间为 2 秒钟。这样一来,如果代码执行时间超过 2 秒钟,就会抛出 TimeoutException 异常。
在我们的示例程序中,由于操作执行时间远远超过了 2 秒钟,因此肯定会抛出TimeoutException 异常。
下面我们来看一个实际应用的示例。假设我们有一个网络请求操作,我们希望在一定时间内获取响应结果,否则就中断该请求并抛出异常。使用超时工具类,我们可以轻松实现该功能。
public class HttpUtils {
public static final int CONNECT_TIMEOUT = 5000;
public static final int READ_TIMEOUT = 5000;
public static String getResponse(String url) throws IOException, TimeoutException {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
.build();
Request request = new Request.Builder().url(url).get().build();
AsyncResult<String> result = new AsyncResult<>();
Callback callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
result.setException(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
result.setResult(response.body().string());
}
};
Call call = client.newCall(request);
call.enqueue(callback);
TimeoutUtils.runWithTimeout(() -> {
// wait for response.
while (!result.isDone()) {
Thread.sleep(100);
}
}, 1000);
if (result.isDone()) {
return result.getResult();
} else {
call.cancel();
throw new TimeoutException("Get response timeout after 1000ms.");
}
}
}
上述代码中,我们定义了一个 HttpUtils
类,其中的 getResponse
方法用来获取 HTTP 返回结果。在该方法中,我们使用了 OkHttpClient 库来进行网络请求,并使用 Callback(回调)来异步获取请求结果。具体来说,我们将回调函数实现为一个内部类,当网络请求成功或失败时,该回调函数的 onResponse
或 onFailure
方法会被自动调用,从而改变 AsyncResult 中的状态。使用 AsyncResult 对象来保存网络请求结果的状态,如果操作超时,则会抛出 TimeoutException 异常。
在 getResponse
方法中,我们使用了 TimeoutUtils.runWithTimeout
方法来控制 HTTP 请求的最长等待时间。具体来说,我们使用一个 while
循环和异步结果对象的 isDone()
方法来判断是否已经完成了 HTTP 响应的获取,如果未能在规定的时间内完成,那么就中止网络请求并抛出异常。值得注意的是,网络请求的取消要用 call.cancel()
方法实现。
总结
本文介绍了如何使用 Java 编写一个超时工具类来限定某个操作的最长执行时间。通过控制线程的等待时间,我们可以达到避免程序出现死锁或者长时间停止运行的目的。上述实现方式简单易行,适用于大量场景。使用超时工具类,我们可以轻松地监控方法的执行时间,并在必要时中断该方法的执行。
本文标题为:Java编写超时工具类实例讲解


基础教程推荐
- java – SQLNestedException:无法创建PoolableConnectionFactory(用户’<>'@ SERVERIP'拒绝访问(使用密码 2023-11-05
- Tomcat网站发布配置方案详细说明 2024-02-25
- synchronized 和 Lock 的异同点(如何让选择) 2023-05-14
- form表单数据封装成json格式并提交给服务器的实现方法 2024-02-26
- java中的实体类时间格式化 2023-02-05
- 利用Mybatis Plus实现一个SQL拦截器 2023-07-14
- JavaMail整合Spring实现邮件发送功能 2023-04-12
- Java Web项目中解决中文乱码方法总结(三种最新方法) 2023-01-13
- Java Spring分别实现定时任务方法 2023-02-28
- 详解Java中的字节码增强技术 2023-06-10