关于异步调用

CompletableFuture.supplyAsync()

以上方法需要一个返回值,然后可以用get方法获取异步任务的结果。但是获取结果时是同步的。如果你写get的地方非常近,就有可能你的异步方法还没执行完毕,还没结果呢,你就开始获取了。所以就会导致变成了同步操作。所以这个get调用,可以放在几个任务之后,别放的离自己任务太近,他就是异步的了。例如代码:

public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        final int[] i = {0,1,2,3,4,5,6,7,8,9,10};
        CompletableFuture<Object> voidCompletableFuture = CompletableFuture.completedFuture(1);

        System.out.println("-------------------");
        Long time = System.currentTimeMillis();
        CompletableFuture<Object> helloWorld = CompletableFuture.supplyAsync(() -> {
            for (Integer a : i) {
                final int finalI = a;
                System.out.println(finalI);
                writeToFile("hello world", "./src/filetest/file" + finalI + ".txt");

            }
            return 1;
        });
        System.out.println("2222222222");
        Object o = null;
        try {
            o = helloWorld.get();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        System.out.println((System.currentTimeMillis() - time)  + "===================");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(o);
        System.out.println((System.currentTimeMillis() - time)  + "--------------------");
    }

    private static void writeToFile(String content, String fileName) {
        try (FileWriter writer = new FileWriter(fileName)) {
            writer.write(content);
        } catch (IOException e) {
            throw new RuntimeException("Error writing to file: " + fileName, e);
        }
    }

以上的代码中,get方法就在异步方法之下导致结果

get方法耗时6毫秒

但是如果放的稍微靠后点

如代码:

public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        final int[] i = {0,1,2,3,4,5,6,7,8,9,10};
        CompletableFuture<Object> voidCompletableFuture = CompletableFuture.completedFuture(1);

        System.out.println("-------------------");
        Long time = System.currentTimeMillis();
        CompletableFuture<Object> helloWorld = CompletableFuture.supplyAsync(() -> {
            for (Integer a : i) {
                final int finalI = a;
                System.out.println(finalI);
                writeToFile("hello world", "./src/filetest/file" + finalI + ".txt");

            }
            return 1;
        });
        System.out.println("2222222222");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        
        System.out.println((System.currentTimeMillis() - time)  + "===================");
        Object o = null;
        try {
            o = helloWorld.get();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        System.out.println(o);
        System.out.println((System.currentTimeMillis() - time)  + "--------------------");
    }

    private static void writeToFile(String content, String fileName) {
        try (FileWriter writer = new FileWriter(fileName)) {
            writer.write(content);
        } catch (IOException e) {
            throw new RuntimeException("Error writing to file: " + fileName, e);
        }
    }

此时结果为:

两次打印时间一样,发现,get方法,不耗费时间。

voidCompletableFuture.thenApplyAsync()

thenApplyAsync方法是一个不要求返回值的异步方法。他的使用过程和上面很相似。只是有一个地方需要提示。

这两个方法,都可以异步执行,上面那个有返回值的,你也可以不去拿返回值,你不取他一样的异步执行。但是但是!!,如果你的主线程,当前线程任务都已经走完了,都return了,而且当前线程也不是一直存活的线程池线程,也就是说如果你的主线程死了。那你的这个异步任务就直接被丢弃了!!!!。

以上红色部分是我在main之中的测试。如果你是一个tomcat服务器中的回调任务,tomcat有自己的主循环,所以一般都可以安全执行完毕。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在使用 Feign 进行异步调用时,你可以通过以下步骤来实现: 1. 配置 Feign 客户端:在你的 Spring Boot 项目中,添加 Feign 的依赖,并在配置类上加上 `@EnableFeignClients` 注解,以启用 Feign 客户端。 2. 创建 Feign 接口:定义一个接口,用于声明需要调用的远程服务的方法。你可以使用 `@FeignClient` 注解来指定所要调用的服务的名称,并使用 `@RequestMapping` 或其他相关注解来定义接口的请求路径和参数。 3. 实现异步调用:在你的 Feign 接口中,可以使用 `@Async` 注解将方法标记为异步调用。然后,你可以在方法体内使用 Spring 的异步支持(如 `CompletableFuture`)来处理异步任务。 以下是一个简单的示例: ```java @FeignClient(name = "remote-service") public interface RemoteServiceClient { @Async @GetMapping("/api/async") CompletableFuture<String> getAsyncData(); } ``` 在上面的示例中,`RemoteServiceClient` 接口定义了一个异步调用的方法 `getAsyncData()`,它将返回一个 `CompletableFuture` 对象,表示异步任务的结果。通过 `@FeignClient` 注解指定了需要调用的远程服务的名称。 然后,在你的业务代码中,你可以通过调用 `getAsyncData()` 方法来发起异步调用,并使用 `CompletableFuture` 来处理异步任务的结果。 需要注意的是,为了使 Feign 客户端支持异步调用,你还需要在项目的配置文件中增加以下配置: ```properties feign.hystrix.enabled=false ``` 这样,Feign 客户端就能够支持异步调用了。希望这能帮到你!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏与ta

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值