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(回调)来异步获取请求结果。具体来说,我们将回调函数实现为一个内部类,当网络请求成功或失败时,该回调函数的 onResponseonFailure 方法会被自动调用,从而改变 AsyncResult 中的状态。使用 AsyncResult 对象来保存网络请求结果的状态,如果操作超时,则会抛出 TimeoutException 异常。

getResponse 方法中,我们使用了 TimeoutUtils.runWithTimeout 方法来控制 HTTP 请求的最长等待时间。具体来说,我们使用一个 while 循环和异步结果对象的 isDone() 方法来判断是否已经完成了 HTTP 响应的获取,如果未能在规定的时间内完成,那么就中止网络请求并抛出异常。值得注意的是,网络请求的取消要用 call.cancel() 方法实现。

总结

本文介绍了如何使用 Java 编写一个超时工具类来限定某个操作的最长执行时间。通过控制线程的等待时间,我们可以达到避免程序出现死锁或者长时间停止运行的目的。上述实现方式简单易行,适用于大量场景。使用超时工具类,我们可以轻松地监控方法的执行时间,并在必要时中断该方法的执行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java编写超时工具类实例讲解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 详解JVM基础之字节码的增强技术

    详解JVM基础之字节码的增强技术 JVM(Java Virtual Machine)是一台虚拟机,它将字节码解释成可执行代码。在Java技术中,字节码是Java类文件中的中间表示形式,并且它是可移植性的关键构成部分。在字节码增强技术中,我们可以使用字节码操作库修改字节码,以实现在程序运行时的动态织入。 一、字节码增强技术的概念 字节码增强技术是在字节码级别上…

    Java 2023年5月26日
    00
  • hibernate框架环境搭建具体步骤(介绍)

    Hibernate是一个Java持久化框架,可以将Java应用程序中的对象映射到关系数据库中的表中。通过Hibernate,Java开发人员可以使用面向对象的方式操作数据库,而不必考虑数据的存取和处理细节。 下面是Hibernate框架环境搭建的具体步骤: 步骤一:引入Hibernate依赖 在项目的pom文件中添加Hibernate依赖,示例代码如下: &…

    Java 2023年5月19日
    00
  • SpringBoot集成FastDFS+Nginx整合基于Token的防盗链的方法

    下面是 SpringBoot 集成 FastDFS+Nginx 整合基于 Token 的防盗链的方法的完整攻略: 简介 FastDFS 是一个开源的分布式文件系统,由阿里巴巴的余庆编写,目前由开源社区进行开发,FastDFS 是基于 Linux 的文件系统,实现了一个简单的文件系统,它是以 Tracker Server 和 Storage Server 为两…

    Java 2023年5月20日
    00
  • Java实现无损Word转PDF的示例代码

    下面是详细讲解“Java实现无损Word转PDF的示例代码”的完整攻略。 1. 准备工作 在开始转换 Word 文档为 PDF 文件之前,需要进行一些准备工作: 安装相应的 Java 开发环境 引入相应的依赖库 将需要转换为 PDF 的 Word 文档准备好 2. 示例代码1 – 使用Apache POI进行文档转换 import java.io.File;…

    Java 2023年5月19日
    00
  • Mybatis中3种关联关系的实现方法示例

    Mybatis中3种关联关系的实现方法示例 Mybatis是一款优秀的ORM框架,可用于实现Java与关系型数据库的交互。在实际开发中,我们经常需要使用到关联查询,Mybatis提供了3种关联关系的实现方式: 一对一(one-to-one)关联 一对多(one-to-many)关联 多对多(many-to-many)关联 以下将分别对这3种关联关系进行详细讲…

    Java 2023年6月1日
    00
  • spring boot2.0总结介绍

    Spring Boot 2.0 总结介绍 Spring Boot 作为一款基于 Spring 框架的快速开发框架,在各种 Web 应用开发过程中被广泛使用。此次我们将对 Spring Boot 2.0 进行总结介绍,分享如何快速搭建、配置和优化 Spring Boot 2.0。 快速搭建 Spring Boot 2.0 搭建 Spring Boot 2.0 …

    Java 2023年5月15日
    00
  • 详解Mybatis模板(已优化)适合小白

    详解Mybatis模板(已优化)适合小白 什么是Mybatis模板? Mybatis模板是Mybatis框架中一种基于Xml和Java代码混合而成的开发模式,它将数据访问和业务逻辑分开,更为灵活、方便,具有可重用性、可扩展性、可维护性、可测试性等等优点,在实际项目开发中得到广泛应用。Mybatis模板中,我们将一些常见的数据库操作进行了封装,以供快速使用,比…

    Java 2023年5月20日
    00
  • Spring-webflux 响应式编程的实例详解

    Spring-webflux 响应式编程的实例详解 响应式编程的概念 响应式编程是一种处理异步数据流的编程范式,其主要思想是通过数据流的变化来触发相应的操作。这种编程模型可以帮助我们更加高效地处理并发、I/O密集型的操作,对于微服务架构的实现尤其有帮助。 Spring-webflux概述 Spring-webflux是基于响应式编程的Spring框架的一个子…

    Java 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部