Spring Boot多线程支持

1简介

最近出差时开发了一个小工具,主要是获取某个摄像头,然后不断的对该摄像头进行抓图,因为抓图比较耗费资源,因此打算使用异步多线程的方式来处理,这样用户在开启多个设备进行抓图时效率更高。如何开启Spring Boot的异步支持吗?本文主要是阐述在工作中使用spring boot的异步任务来应对工作中的并发编程问题。

2操作步骤

2.1项目结构

Spring Boot多线程支持_第1张图片

2.2项目pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.cetc52groupId>
    <artifactId>testThreadartifactId>
    <version>1.0-SNAPSHOTversion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.0.3.RELEASEversion>
        <relativePath/> 
    parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
    dependencies>
project>

2.2AsyncConfig

Spring通过任务执行器TaskExecutor来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。而实际开发中任务一般是非阻碍的,即异步的,所以我们要在配置类中通过@EnableAsync开启对异步任务的支持,并通过在实际执行的Bean的方法中使用@Async注解来声明其是一个异步任务。

package com.cetc52.testthread.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 开启异步执行的配置类
 *
 * @Owner:
 * @Time: 2019/3/24-21:25
 */

@Configuration
@EnableAsync
@ComponentScan("com.cetc52.testthread.service")
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setQueueCapacity(25);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

2.3AsyncTaskService

package com.cetc52.testthread.service;

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

/**
 * 异步任务执行类
 *
 * @Owner:
 * @Time: 2019/3/24-21:30
 */
@Service
public class AsyncTaskService {
    @Async
    public void executeAsyncTask(Integer i) {
        System.out.println("执行异步任务: "+i);
    }

    @Async
    public void executeAsyncTaskPlus(Integer i) {
        System.out.println("执行异步任务+1: " + (i+1));
    }
}

Spring Boot多线程支持_第2张图片

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
    String value() default "";
}

注意:@Async注解表明该方法是个异步方法。从上述的Async注解接口可以看到,Target即可以在方法也可以在类型上,如果注解在类型上,表明该类所有的方法都是异步方法。
从上图可以看到Async注解由spring-context包提供。

2.4Main类演示效果

package com.cetc52.testthread;

import com.cetc52.testthread.service.AsyncTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * Main
 *
 * @Owner:
 * @Time: 2019/3/24-21:21
 */
@SpringBootApplication
public class TestThreadApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(TestThreadApplication.class, args);

        AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);
        for (int i = 0; i < 10; i++) {
            asyncTaskService.executeAsyncTask(i);
            asyncTaskService.executeAsyncTaskPlus(i);
        }
        System.out.println("This Program has Begun successfully");

    }
}

项目执行可以在Console中打印如下的结果,表明确实项目确实是多线程在执行

This Program has Begun successfully
执行异步任务: 2
执行异步任务+11
执行异步任务: 1
执行异步任务+12
执行异步任务+14
执行异步任务: 0
执行异步任务+15
执行异步任务: 4
执行异步任务+13
执行异步任务: 3
执行异步任务+17
执行异步任务: 6
执行异步任务+16
执行异步任务: 5
执行异步任务+19
执行异步任务: 8
执行异步任务+18
执行异步任务: 7
执行异步任务+110
执行异步任务: 9

3线程与线程理解

参见深入理解线程和线程池(图文详解)

3.1关于线程

Spring Boot多线程支持_第3张图片

3.2线程池

public ThreadPoolExecutor(int corePoolSize,  
                              int maximumPoolSize,  
                              long keepAliveTime,  
                              TimeUnit unit,  
                              BlockingQueue<Runnable> workQueue,  
                              ThreadFactory threadFactory,  
                              RejectedExecutionHandler handler)

3.2.1线程池概述图

线程池主要内容如图所示:
Spring Boot多线程支持_第4张图片

3.2.2线程池类型

Spring Boot多线程支持_第5张图片

4总结

本文简要描述了Spring Boot对异步任务的支持,通过Demo可以很好的结合自己的项目,从代码中可以看出异步任务在Spring Boot支持的很优雅。在本文中也简单的介绍了线程和线程池的概念。具体可以参考深入理解线程和线程池(图文详解)

										2019-03-24 22:23于江宁麒麟科技园

你可能感兴趣的:(Spring,Boot)