Spring Boot笔记—多线程系列(一)—使用多线程

1 使用场景

​ 在Spring Boot项目中,有时候需要单独监控某一个业务,或者需要在主流程之外单独处理一些数据。

​ 在Spring项目中,由于Bean 对象是spring容器管理的,直接new出来的对象是没法使用bean里面依赖的其他组件,如dao,mapper等。此时,如果想使用bean里依赖的其他组件,则需要spring的多线程。

此篇文章,只是介绍了使用spring多线程的简单方式。至于多线程的参数设置,自定义线程池等将在另外的文章详解。

2 实现方式

2.1 使用Spring封装的异步

2.1.1 介绍

Spring Boot开启异步,需要两个注解:@EnableAsync和@Async。

  • @EnableAsync

    在配置类中通过添加该注解,开启对异步任务的支持。

  • @Async

    在实际执行的bean的方法中使用该注解表名这是一个异步任务。

2.1.2 样例

2.1.2.1 目录结构

Study
├── src
│   ├── main
│   │   ├── java
│   │   │   └── top
│   │   │       └── yxdz
│   │   │           └── study
│   │   │               ├── StudyApplication.java
│   │   │               └── spring
│   │   │                   └── springboot
│   │   │                       └── thread
│   │   │                           └── service
│   │   │                               ├── ITestService.java
│   │   │                               └── impl
│   │   │                                   └── TestSerivceImpl.java
│   └── test
│       └── java
│           └── top
│               └── yxdz
│                   └── study
│                       └── StudyApplicationTests.java

2.1.2.2 代码

  • StudyApplicationTests——测试入口

    这是测试类,也是配置类,添加了注解@EnableAsync,用来在此测试中启用异步。

    package top.yxdz.study;
    
    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.scheduling.annotation.EnableAsync;
    import org.springframework.test.context.junit4.SpringRunner;
    import top.yxdz.study.spring.springboot.thread.service.ITestService;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @EnableAsync
    public class StudyApplicationTests {
    
        @Autowired
        ITestService iTestService;
    
        @Test
        public void contextLoads() {
    
            for(int i=0; i<5; i++){
                iTestService.method1("Async" + i);
            }
    
            try {
                //等待10s,防止异步代码被强制关闭导致线程抛出异常
                Thread.sleep(10000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
    
  • ITestService——测试类接口

    package top.yxdz.study.spring.springboot.thread.service;
    
    public interface ITestService {
    
        /**
         * 异步测试
         * @param msg
         */
        void method1(String msg);
    }
    
  • TestSerivceImpl——测试类实现

    这是实现类,在实现函数上添加了注释@Async表示异步调用。

    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    import top.yxdz.study.spring.springboot.thread.service.ITestService;
    
    import java.time.LocalDateTime;
    
    
    @Service("TestSerivceImpl")
    public class TestSerivceImpl implements ITestService {
    
        private static Logger LOG = LoggerFactory.getLogger(TestSerivceImpl.class);
    
        @Override
        @Async
        public void method1(String msg){
    
            try {
                LOG.info(LocalDateTime.now().toString() + msg);
                Thread.sleep(1000);
                LOG.info(LocalDateTime.now().toString() + msg);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
    

2.1.2.3 执行结果

  • 执行结果

    2018-12-12 20:07:37.631  INFO 34428 --- [         task-5] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:37.631Async4
    2018-12-12 20:07:37.631  INFO 34428 --- [         task-1] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:37.631Async0
    2018-12-12 20:07:37.631  INFO 34428 --- [         task-4] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:37.631Async3
    2018-12-12 20:07:37.631  INFO 34428 --- [         task-2] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:37.631Async1
    2018-12-12 20:07:37.631  INFO 34428 --- [         task-3] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:37.631Async2
    2018-12-12 20:07:38.635  INFO 34428 --- [         task-4] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:38.635Async3
    2018-12-12 20:07:38.635  INFO 34428 --- [         task-2] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:38.635Async1
    2018-12-12 20:07:38.635  INFO 34428 --- [         task-3] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:38.635Async2
    2018-12-12 20:07:38.635  INFO 34428 --- [         task-1] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:38.635Async0
    2018-12-12 20:07:38.635  INFO 34428 --- [         task-5] t.y.s.s.s.t.s.impl.TestSerivceImpl       : 2018-12-12T20:07:38.635Async4
    
  • 结果说明

    该方式使用的是异步,执行iTestService.method1("Async" + i);时,会开一个线程执行,并不会影响主线程的运行,for循环会毫无障碍(不会受Thread.sleep(1000)的影响)运行完毕,同时也会产生四个线程,独立运行method1方法。

    因为是四个线程独立运行的结果,所以结果的顺序并不能保证每次一致。

posted @ 2018-12-14 09:01  悠闲的宅  阅读(684)  评论(0编辑  收藏  举报