SpringBoot实现异步操作

分类:
JAVA
标签:
SpringBoot
线程
异步
作者:
何鑫
创作时间:
2019/07/30 21:57:34

摘要:SpringBoot实现异步操作

异步调用

在实际工作中,我们可能会遇到需要异步执行的操作,比如添加日志,如果同步操作,加上数据库开销,可能会影响原本程序的执行效率,我们一般的做法有两种,第一种,推送到消息队列,如redis,kafka等,第二种,单独开一个线程去处理日志。我们这里主要关注第二种。

传统方式

创建线程的方式主要有两种,一种是继承Thread类,第二种是实现Runable接口,但在实际运用中,我们一般不显式创建线程,而是要使用线程池,实现对线程的统一管理,从而避免线程资源耗尽,影响服务正常运行,下面是一个示例:

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
ExecutorService executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory);
executorService.execute(() -> {
    // 业务逻辑
});

SpringBoot异步操作

SpringBoot给我们提供了一种简单的方式来实现异步操作。

首先我们需要在启动类上添加注解:@EnableAsync表示启用异步操作。

package cn.besthexin.lab;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync // 启用异步操作
public class LabApplication {

    public static void main(String[] args) {
        SpringApplication.run(LabApplication.class, args);
    }

}

在service创建一个用于异步执行的方法,并在方法上加上注解@Async:

package cn.besthexin.lab.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class LabService {

    @Async // 表示异步操作
    public void test() {
        try {
            Thread.sleep(10000); // 线程休眠来模拟耗时操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行完成,现在时间:" + LocalDateTime.now().toString());
    }

}

在controller层写一个方法用于测试:

package cn.besthexin.lab.controller;

import cn.besthexin.lab.service.LabService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LabController {

    @Autowired
    private LabService labService;


    @GetMapping("/hello")
    public String test() {
        labService.test();
        return "现在时间:" + LocalDateTime.now();
    }
}

启动SpringBoot,请求此路径:

页面输出:现在时间:2019-07-30T21:51:36.821462500

10秒钟后,控制台输出:执行完成,现在时间:2019-07-30T21:51:46.791753200

可以看到,我们已经实现了异步操作。

需要特别注意的是,需要异步调用的方法与调用方不可以在同一个类中,否则异步操作会失效!

发表评论

温馨提示: 评论先审核后发布, 请勿发表不良言论

所有评论