SpingBoot @Async的使用

项目工程结构

image

定义一个业务类,有4个业务

package com.demo.testasync.service;

import java.util.concurrent.Future;

public interface TestService {

    /**
     * 异步调用,无返回值
     */
    void asyncTask1();

    /**
     * 异步调用,无返回值
     */
    void asyncTask2();

    /**
     * 异步调用,有返回值
     *
     * @param s 年代
     * @return {@link Future}
     * Future表示一个可能还没有完成的异步任务的结果
     */
    Future asyncTask1(String s);

    /**
     * 异步调用,有返回值
     *
     * @param s 年代
     * @return {@link Future}
     * Future表示一个可能还没有完成的异步任务的结果
     */
    Future asyncTask2(String s);



}

业务实现类


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

import java.util.concurrent.Future;

@Service
public class TestServiceImpl implements TestService {



    @Async("doAsyncTaskExecutor")
    @Override
    public void asyncTask1() {
        long startTime = System.currentTimeMillis();

        // 模拟耗时
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        System.out.println(Thread.currentThread() + ",asyncTask(),耗时:" + (endTime - startTime));

    }

    @Async("doAsyncTaskExecutor")
    @Override
    public void asyncTask2() {
        long startTime = System.currentTimeMillis();

        // 模拟耗时
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        System.out.println(Thread.currentThread() + ",asyncTask(),耗时:" + (endTime - startTime));

    }

    @Async("doAsyncTaskExecutor")
    @Override
    public Future asyncTask1(String s) {
        long startTime = System.currentTimeMillis();

        // 模拟耗时
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        System.out.println(Thread.currentThread() + ",asyncTask(String s),耗时:" + (endTime - startTime));

        return AsyncResult.forValue(s);
    }

    @Async("doAsyncTaskExecutor")
    @Override
    public Future asyncTask2(String s) {
        long startTime = System.currentTimeMillis();

        // 模拟耗时
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        System.out.println(Thread.currentThread() + ",asyncTask(String s),耗时:" + (endTime - startTime));

        return AsyncResult.forValue(s);
    }
}

线程池配置

配置完成后@Async会默认从线程池获取线程,当然也可以显式的指定@Async("doAsyncTaskExecutor")

package com.demo.testasync.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class AsyncConfig {

    private static final int MAX_POOL_SIZE = 500;

    private static final int CORE_POOL_SIZE = 20;

    @Bean("doAsyncTaskExecutor")
    AsyncTaskExecutor doAsyncTaskExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        threadPoolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        //配置最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        //配置队列大小
        threadPoolTaskExecutor.setQueueCapacity(200);
        //线程池维护线程所允许的空闲时间
        threadPoolTaskExecutor.setKeepAliveSeconds(30);
        //配置线程池中的线程的名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("yoyo");
        //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        //设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
        threadPoolTaskExecutor.setAwaitTerminationSeconds(60);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        threadPoolTaskExecutor.initialize();


        return threadPoolTaskExecutor;
    }

}

在ApplicationRunner中初始化业务方法的实现,这样启动项目后,业务方法会自动异步执行

package com.demo.testasync.job;

import com.demo.testasync.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class RunThread {

    @Autowired
    TestService testService;

    @Bean
    public ApplicationRunner applicationRunner() {
        return applicationArguments -> {
            long startTime = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName() + ":开始调用异步业务");

            //无返回值
            testService.asyncTask1();
            testService.asyncTask2();
            testService.asyncTask1("haha1");
            testService.asyncTask2("haha2");

            long endTime = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName() + ":调用异步业务结束,耗时:" + (endTime - startTime));
        };
    }


}

在启动类上加上@EnableAsync注解

package com.demo.testasync;

import com.demo.testasync.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

@SpringBootApplication
@EnableAsync
public class TestasyncApplication {

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

}

效果

image

posted @ 2021-09-23 14:57  西红柿里没有番茄  阅读(63)  评论(0编辑  收藏  举报