Spring Cloud微服务实战 打造企业级优惠券系统 3-7 SpringBoot 异步任务(任务池)

0    课程地址

http://coding.imooc.com/lesson/380.html#mid=28275

1    浓缩精华
1.1  浓缩精华

4.2  多个线程池的配置使用

2    个人关注
2.1  个人关注

4.1  异步任务demo

4.2  线程池的配置使用

4.2  多个线程池的配置使用

4.2  TimeUnit.SECONDS.sleep(5);的使用

4.3  超时方法使用

3    课程内容
3.1  4.1,4.2
4    代码演练
4.1  异步任务demo(非线程池)

测试类

package com.imooc.springboot.application;

import com.imooc.springboot.application.async.AsyncService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * TestAsyncService
 *
 * @author 魏豆豆
 * @date 2021/4/6
 */
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestAsyncService {

    @Autowired
    private AsyncService asyncService;

    @Test
    public void executeAsyncService() throws InterruptedException {
        asyncService.asyncNotReturn();
        log.info("进入无参异步方法");
    }

    @Test
    public void executeAsyncService2() throws InterruptedException {
        asyncService.asyncHasReturn();
        //Thread.sleep(10);
        log.info("进入有参异步方法");
    }

}

异步任务Service

package com.imooc.springboot.application.async;

import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * AsyncService
 *
 * @author 魏豆豆
 * @date 2021/4/6
 */
@Slf4j
@Service
public class AsyncService {

    /**
     * 没有返回的异步任务
     */
    @Async
    public void asyncNotReturn() throws InterruptedException {
        //记一下sleep
        log.info("无返回线程名字为======================="+Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(5);
    }

    /**
     * 没有返回的异步任务
     * @return
     */
    @Async
    public Future<Integer> asyncHasReturn() throws InterruptedException {
        log.info("有返回线程名字为======================="+Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(6);

        //记一下
        return new AsyncResult<>(100);
    }

}

顶部启动类:

package com.imooc.springboot.application;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * SpringBootApplication
 *
 * @author 魏豆豆
 * @date 2021/1/13
 */
@SpringBootApplication
@EnableScheduling
@EnableAsync//允许异步任务
public class SpringBootStudyApplication {
    public static void main(String [] args){
        //第一种方式启动
        //SpringApplication.run(SpringBootStudyApplication.class,args);

        //第二种方式启动
        /*SpringApplication springApplication = new SpringApplication(SpringBootStudyApplication.class);
        //关掉打印logo相关日志
        springApplication.setBannerMode(Banner.Mode.OFF);
        //非wub启动,控制台启动后会关闭,不会一直保持开启状态
        springApplication.setWebApplicationType(WebApplicationType.NONE);
        springApplication.run(args);*/

        //第三种方式启动 链式调用
       new SpringApplicationBuilder(SpringBootStudyApplication.class)
                //.bannerMode(Banner.Mode.OFF)
               // .web(WebApplicationType.NONE)
               .run(args);
    }

}

打印日志:

2021-04-11 07:46:03.139  INFO 16808 --- [           main] c.i.s.application.TestAsyncService       : 进入无参异步方法
2021-04-11 07:46:03.149  INFO 16808 --- [           main] c.i.s.application.TestAsyncService       : 进入有参异步方法
2021-04-11 07:46:03.159  INFO 16808 --- [cTaskExecutor-1] c.i.s.application.async.AsyncService     : 无返回线程名字为=======================SimpleAsyncTaskExecutor-1
2021-04-11 07:46:03.160  INFO 16808 --- [cTaskExecutor-2] c.i.s.application.async.AsyncService     : 有返回线程名字为=======================SimpleAsyncTaskExecutor-2
2021-04-11 07:46:03.168  INFO 16808 --- [       Thread-2] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'
2021-04-11 07:46:03.187  INFO 16808 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'bbb'
4.2  异步任务demo(线程池配置)

测试类

package com.imooc.springboot.application;

import com.imooc.springboot.application.async.AsyncService2;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * TestAsyncService
 *
 * @author 魏豆豆
 * @date 2021/4/6
 */
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestAsyncService2 {

    @Autowired
    private AsyncService2 asyncService;

    @Test
    public void executeAsyncService() throws InterruptedException {
        asyncService.asyncNotReturn();
        log.info("进入无参异步方法");
    }

    @Test
    public void executeAsyncService2() throws InterruptedException, ExecutionException {
        //记一下时间的
        long start = System.currentTimeMillis();
        System.out.println("start=========================="+start);
        Future<Integer> future = asyncService.asyncHasReturn();

        //Thread.sleep(10);
        log.info("进入有参异步方法");
        log.info("future.get",future.get());
        log.info("时间差=====",System.currentTimeMillis()-start);
    }

}

异步任务Service2

package com.imooc.springboot.application.async;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * AsyncService
 *
 * @author 魏豆豆
 * @date 2021/4/6
 */
@Slf4j
@Service
public class AsyncService2 {

    /**
     * 没有返回的异步任务
     */
    @Async("aaa")
    public void asyncNotReturn() throws InterruptedException {
        //记一下sleep
        log.info("无返回自定义线程名字为======================="+Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(5);
    }

    /**
     * 没有返回的异步任务
     * @return
     */
    @Async("bbb")
    public Future<Integer> asyncHasReturn() throws InterruptedException {
        log.info("有返回自定义线程名字为======================="+Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(6);

        //记一下
        return new AsyncResult<>(100);
    }

}

线程池配置类:

package com.imooc.springboot.application.config;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * AsyncThreadPoolConfig
 * 自定义线程池
 * @author 魏豆豆
 * @date 2021/4/7
 */
@Configuration
@Slf4j
//记一下实现的接口(实现异步任务配置类)
public class AsyncThreadPoolConfig implements AsyncConfigurer {


    @Bean//将线程池初始化到springioc容器中
    public Executor aaa() {
        //1     线程池设置参数
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(20);//核心线程20个,能同时处理20个客户端请求
        threadPoolTaskExecutor.setQueueCapacity(10);//缓冲队列允许10个线程等待
        threadPoolTaskExecutor.setMaxPoolSize(30);//超出缓冲队列最多允许30个线程处理
        threadPoolTaskExecutor.setKeepAliveSeconds(60);//线程存活时间60秒
        threadPoolTaskExecutor.setThreadNamePrefix("wdd_");//线程名称前缀

        //记一下
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskExecutor.setAwaitTerminationSeconds(60);

        //2     拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        //3     线程池初始化
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Bean//将线程池初始化到springioc容器中
    public Executor bbb() {
        //1     线程池设置参数
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(20);//核心线程20个,能同时处理20个客户端请求
        threadPoolTaskExecutor.setQueueCapacity(10);//缓冲队列允许10个线程等待
        threadPoolTaskExecutor.setMaxPoolSize(30);//超出缓冲队列最多允许30个线程处理
        threadPoolTaskExecutor.setKeepAliveSeconds(60);//线程存活时间60秒
        threadPoolTaskExecutor.setThreadNamePrefix("hcx_");//线程名称前缀

        //记一下
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskExecutor.setAwaitTerminationSeconds(60);

        //2     拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        //3     线程池初始化
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }


    /**
     * 该方法仅能处理无返回值异步任务的异常,有返回值的异步任务异常客户端处理
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncExceptionHandler();
    }

    //记一下,异常处理类实现异常处理接口
    class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler{

        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
            //1     打印日志
            log.info("wdd异常打印========"+throwable.getMessage(),method.getName(),JSON.toJSONString(objects));

            //2     正常跑出异常
            throwable.printStackTrace();

            //3     发短信或者邮件通知运维人员
            //todo
        }
    }
}

顶部启动类:(同上)

打印日志:

2021-04-11 07:48:51.441  INFO 15872 --- [           main] c.i.s.application.TestAsyncService2      : 进入无参异步方法
start==========================1618098531455
2021-04-11 07:48:51.455  INFO 15872 --- [           main] c.i.s.application.TestAsyncService2      : 进入有参异步方法
2021-04-11 07:48:51.492  INFO 15872 --- [          hcx_1] c.i.s.application.async.AsyncService2    : 有返回自定义线程名字为=======================hcx_1
2021-04-11 07:48:51.492  INFO 15872 --- [          wdd_1] c.i.s.application.async.AsyncService2    : 无返回自定义线程名字为=======================wdd_1
2021-04-11 07:48:57.504  INFO 15872 --- [           main] c.i.s.application.TestAsyncService2      : future.get
2021-04-11 07:48:57.504  INFO 15872 --- [           main] c.i.s.application.TestAsyncService2      : 时间差=====
2021-04-11 07:48:57.520  INFO 15872 --- [       Thread-2] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'
2021-04-11 07:48:57.520  INFO 15872 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'bbb'
2021-04-11 07:48:57.520  INFO 15872 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'aaa'
4.3  异步任务demo(超时方法应用)

测试类:

 @Test
    public void executeAsyncService2() throws InterruptedException, ExecutionException, TimeoutException {
        //记一下时间的
        long start = System.currentTimeMillis();
        System.out.println("start=========================="+start);
        Future<Integer> future = asyncService.asyncHasReturn();

        //Thread.sleep(10);
        log.info("进入有参异步方法");
        //log.info("future.get",future.get());
        log.info("超时方法=======================",future.get(1,TimeUnit.SECONDS));
        log.info("时间差=====",System.currentTimeMillis()-start);
    }

其他方法如4.2

打印日志:

start==========================1618099228046
2021-04-11 08:00:28.055  INFO 11628 --- [           main] c.i.s.application.TestAsyncService2      : 进入有参异步方法
2021-04-11 08:00:28.065  INFO 11628 --- [          hcx_1] c.i.s.application.async.AsyncService2    : 有返回自定义线程名字为=======================hcx_1

java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at com.imooc.springboot.application.TestAsyncService2.executeAsyncService2(TestAsyncService2.java:46)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

2021-04-11 08:00:29.075  INFO 11628 --- [       Thread-2] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'
2021-04-11 08:00:29.079  INFO 11628 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'bbb'
2021-04-11 08:00:34.068  INFO 11628 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'aaa'

Process finished with exit code -1
诸葛
原文地址:https://www.cnblogs.com/1446358788-qq/p/14296099.html