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
执行异步任务+1: 1
执行异步任务: 1
执行异步任务+1: 2
执行异步任务+1: 4
执行异步任务: 0
执行异步任务+1: 5
执行异步任务: 4
执行异步任务+1: 3
执行异步任务: 3
执行异步任务+1: 7
执行异步任务: 6
执行异步任务+1: 6
执行异步任务: 5
执行异步任务+1: 9
执行异步任务: 8
执行异步任务+1: 8
执行异步任务: 7
执行异步任务+1: 10
执行异步任务: 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于江宁麒麟科技园