Spring Boot多线程支持

1简介

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

2操作步骤

2.1项目结构

在这里插入图片描述

2.2项目pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>com.cetc52</groupId>
    <artifactId>testThread</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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));
    }
}

在这里插入图片描述

@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关于线程

在这里插入图片描述

3.2线程池

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

3.2.1线程池概述图

线程池主要内容如图所示:
在这里插入图片描述

3.2.2线程池类型

在这里插入图片描述

4总结

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

										2019-03-24 22:23于江宁麒麟科技园
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值