项目中发现了一个新的玩意WebAsyncTask

简介: 前言文本已收录至我的GitHub仓库,欢迎Star:github.com/bin39232820…种一棵树最好的时间是十年前,其次是现在

絮叨


刚好在读项目代码的时候,发现了WebAsyncTask这个新玩意,给大家来科普科普,不是那么的深入,不喜勿喷!

网络异常,图片无法展示
|
网络异常,图片无法展示
|


SpringBoot中同异步调用的使用


异步请求的处理。除了异步请求,一般上我们用的比较多的应该是异步调用。通常在开发过程中,会遇到一个方法是和实际业务无关的,没有紧密性的。比如记录日志信息等业务。这个时候正常就是启一个新线程去做一些业务处理,让主线程异步的执行其他业务。

  • 同步请求

网络异常,图片无法展示
|


  • 异步请求

网络异常,图片无法展示
|


SprinBoot中@Async异步方法


异步的好处是,可以提高程序吞吐量,一个任务,让耗时的异步处理,并继续同步处理后面的任务,异步任务可以返回结果,拿到结果后可结合同步处理过程中的变量一起处理计算


具体的使用

在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。


自定义线程池异步调用

配置@EnableAsync使@Async生效

@SpringBootApplication
@EnableAsync
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
复制代码


自定义线程池

@Component
@Scope  //单例
public class MyExecutePoll {
    @Bean
    public Executor myAsyncPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(20);
        //最大线程数
        executor.setMaxPoolSize(40);
        //队列容量
        executor.setQueueCapacity(50);
        // 活跃时间
        executor.setKeepAliveSeconds(300);
        // 线程名字前缀
        executor.setThreadNamePrefix("MyExecutor-");
        //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean,使异步线程的销毁优先于Redis等其他处理报错
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
        executor.setAwaitTerminationSeconds(60);
        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}
复制代码


使用@Async

@Async("myAsyncPool")   //@Async使用默认的线程
public Future<String> doTask() throws Exception {
    //业务处理   使用Future返回异步调用结果
    return new AsyncResult<>("任务一完成");
复制代码


在Spring中运用 Async注解 需要注意几点:

  • AsyncTest.java,测试类,调用异步任务,同时执行同步方法
  • OrderService.java,异步任务类,提供异步方法
  • AsyncThreadPoolConfig.java,异步任务线程池配置类,配置异步任务运行的线程池大小等


基于Spring实现异步请求


Spring可以通过Callable或者WebAsyncTask等方式实现异步请求, 我们来看看,这2种实现方式!


Callable

Callable是为了异步生成返回值提供基本的支持。简单来说就是一个请求进来,如果你使用了Callable,在没有得到返回数据之前,DispatcherServlet和所有Filter就会退出Servlet容器线程,但响应保持打开状态,一旦返回数据有了,这个DispatcherServlet就会被再次调用并且处理,以异步产生的方式,向请求端返回值。 这么做的好处就是请求不会长时间占用服务连接池,提高服务器的吞吐量。


@GetMapping("/callable")
    public Callable<String> testCallable() throws InterruptedException {
        log.info("主线程开始!");
        Callable<String> result = new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("副线程开始!");
                Thread.sleep(1000);
                log.info("副线程结束!");
                return "SUCCESS";
            }
        };
        log.info("主线程结束!");
        return result;
    }
复制代码


输出结果

主线程开始!
主线程结束!
副线程开始!
副线程结束!
复制代码


WebAsyncTask

一个请求到服务上,是用的web容器的线程接收的

我们可以使用WebAsyncTask将这个请求分发给一个新的线程去执行,容器的线程可以去接收其他请求的处理。一旦WebAsyncTask返回数据有了,就会被再次调用并且处理,以异步产生的方式,向请求端返回值,但是其实我觉得前端的请求rt并不会说变短。

/**
     * 查询
     */
    @RequestMapping(method = RequestMethod.GET, value = "/aysncTask/{testId}")
    @ResponseStatus(HttpStatus.OK)
    public WebAsyncTask<Response> aysncTask(@PathVariable("testId") String testId) {
        System.out.println(String.format("/aysncTask/%s 被调用 thread id is: %s", testId,Thread.currentThread().getName()));
        Callable<Response> callable = () -> {
            Thread.sleep(1000L);
            Response response = new Response(true,"异步执行成功");
            System.out.println(String.format("/aysncTask/%s 被调用 thread id is: %s", testId,Thread.currentThread().getName()));
            return response;
        };
        return new WebAsyncTask<Response>(callable);
    }
复制代码


控制台打印如下: 在执行业务逻辑之前的线程和具体处理业务逻辑的线程不是同一个,达到了我们的目的。async-customize-1这个前缀是我们自定义的下边会说

/aysncTask/12348567676 被调用 thread id is: http-nio-8084-exec-1
/aysncTask/12348567676 被调用 thread id is: async-customize-1
复制代码


其实WebAsyncTask比起Callable是有以下几个优点的

官方有这么一句话,截图给你:

网络异常,图片无法展示
|
如果我们需要超时处理的回调或者错误处理的回调,我们可以使用WebAsyncTask代替Callable

实际使用中,我并不建议直接使用Callable ,而是使用Spring提供的WebAsyncTask 代替,它包装了Callable,功能更强大些


总结


其实本文就是给大家科普下,一些异步的用法,不至于说看到人家这么用很蒙b,多线程的东西还是优点东西的,大家一起学习。

相关文章
|
5月前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
754 3
|
存储 Kubernetes 应用服务中间件
【K8S系列】深入解析无状态服务
【K8S系列】深入解析无状态服务
873 2
|
机器学习/深度学习 人工智能 算法
|
移动开发 前端开发 语音技术
WordPress轻拟物博客主题niRvana 4.5.3(自适应手机端)
WordPress轻拟物主题niRvana,设计上不再趋从于现有的扁平风,我认为是时候从极致的扁平稍微向拟物致敬了,因此采用了轻拟物的风格。niRvana 设计和样式更加新颖,一眼看上去就会被他吸引住,主题配色也非常舒服。而且它有两个功能特别有意思,一个是自动根据文章特色图片识别出图片的主色调,在首页、文章分类页用最美的方式显示滚动图片,另一个则是文章支持语音朗读。主题细腻有质感,手机端体验非常好。
243 2
|
10月前
|
数据采集 人工智能 搜索推荐
DeepSeek告诉你眼中不会被AI替代的职业,打工人可以这样华丽转型
在AI技术飞速发展的今天,职场正经历前所未有的变革。麦肯锡预测,到2030年全球约30%的岗位可能被AI替代,但AI并非终结者,而是转型推手。DeepSeek揭示了教育、医疗、手工艺和创意等难以被AI替代的职业领域,并提供了从“被替代者”到“AI指挥官”的转型指南。生成式人工智能(GAI)认证成为提升自我、适应AI时代的关键工具,助力职场人掌握核心技能,实现华丽转型。未来赢家将是善用AI放大自身优势的人。
|
SQL 存储 Oracle
南大通用GBase 8s数据库游标变量解析:提升数据库操作效率
南大通用GBase 8s 数据库游标变量解析:提升数据库操作效率
|
JavaScript 开发者
在软件开发中,代码规范至关重要,TypeScript 和 ESLint 是提升代码质量和团队协作效率的两大利器
在软件开发中,代码规范至关重要,TypeScript 和 ESLint 是提升代码质量和团队协作效率的两大利器。TypeScript 通过类型检查、接口定义和模块系统增强代码规范;ESLint 则专注于语法检查、风格统一和最佳实践。二者结合使用,能有效提高代码的可读性、可维护性,促进团队协作。制定合理的代码规范策略,注重团队共识、灵活性和持续优化,是确保项目成功的基石。
258 5
|
NoSQL JavaScript 算法
Higress 全新 Wasm 运行时,性能大幅提升
本文介绍 Higress 将 Wasm 插件的运行时从 V8 切换到 WebAssembly Micro Runtime (WAMR) 的最新进展。
55875 97
|
JavaScript 小程序 测试技术
iphone13到底香不香,真的这么难抢?
本文介绍了iPhone 12/13的自动化测试脚本,包括Node.js脚本实现有货通知和Python+Selenium自动化抢购脚本。Node.js脚本可在检测到有货时发送邮件通知;Python+Selenium脚本则能模拟用户操作,完成从选择型号、颜色到支付的全过程。
267 7
iphone13到底香不香,真的这么难抢?
|
安全 Java 程序员
【多线程-从零开始-肆】线程安全、加锁和死锁
【多线程-从零开始-肆】线程安全、加锁和死锁
260 0

热门文章

最新文章