SpringBoot中异步方法的使用

1. 使用CompletableFuture

实例如下:

@Autowired
@Resource(name = "threadPoolTaskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;

@GetMapping
    public String testAsync() {
        CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步方法执行成功2, 线程名: " + Thread.currentThread().getName());
            return "异步方法执行成功";
            // 这里可传入值自定义的线程池, 否则是默认
        }, threadPoolTaskExecutor);
        return "success";
    }
2. 通过 @Async 注解

参数是 线程池对象名

这里直接在同一个类中是不行了, 错误方式如下:

// 这样还是一个同步方法
    @GetMapping
    public String testAsync() {
        test();
        return "success";
    }

    @Async("threadPoolTaskExecutor")
    public void test() {
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("异步方法执行成功");
    }

// 这段代码中虽然使用了@Async注解来标记test方法,
// 但在testAsync方法中直接调用了test方法,而没有通过异步的方式调用。
// 在Spring框架中,@Async注解只能在其他bean方法内部被调用,
// 因为它通过创建一个代理对象来实现异步调用
正确方式1
  1. 定义一个共同的bean用来处理异步方法

    @Data
    @Component
    public class CommonAsyncComponent {
        
            @Async("threadPoolTaskExecutor")
        public void test() {
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步方法执行成功");
        }
    
    }
    

    主方法中调用

        @Autowired
        private CommonAsyncComponent commonAsyncComponent;
        
        @GetMapping
        public String testAsync(){
            commonAsyncComponent.test();
            return "success";
        }
        
    
正确方式2

在server的实现类中直接使用**@Async**注解, 这样在控制层调用时就直接是异步方法

    @Override
    @Async("threadPoolTaskExecutor")
    public void test() {
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("service异步方法执行成功");
    }
3. 使用Thread

这里是创建一个新的线程来执行, 而不是从线程池中直接获取, 但是存在一些问题

  1. 可维护性:直接创建线程可能导致代码可读性和可维护性降低,尤其是在复杂的应用中。
  2. 控制性差:线程的生命周期和资源管理需要手动处理,容易导致资源泄漏或线程安全问题。
  3. 可扩展性差:对于大规模应用,手动管理线程可能不是最优选择,因为它难以扩展和优化。
       new Thread(() -> {
       try {
            Thread.sleep(10000L);
       } catch (InterruptedException e) {
            e.printStackTrace();
       }
       System.out.println("controller异步方法执行成功");
       }).start();

你可能感兴趣的:(java,开发语言)