TaskExecutor 异步线程池

Spring基础学习-任务执行(TaskExecutor及Async)

ExecutorService和TaskExecutor的区别和使用

spring的TaskExecutor的两个常用实现类均是基于Executor实现类的包装,使其更加方便使用,更好的融入spring bean生态。

controller/HelloController.java

package com.boot.study.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.boot.study.service.AsyncService;

@RestController
@RequestMapping("/hello")
public class HelloController {

	@Autowired
	private TaskExecutor taskExecutor;

	@GetMapping("/map")
	public Map<String, Object> map() {
		Map<String, Object> map = new HashMap<>();
		map.put("name", "revin");
		map.put("age", 18);

		taskExecutor.execute(new Runnable() {

			@Override
			public void run() {
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.out.println("我醒了22");
			}
		});

		return map;
	}
}

config/Configs.java

注册配置

package com.boot.study.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

//@EnableAsync
@Configuration
public class Configs {

	@Bean
	public TaskExecutor taskExecutor() {
		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
		taskExecutor.setCorePoolSize(10);
		taskExecutor.setMaxPoolSize(50);

		return taskExecutor;
	}
}

HelloController.java直接使用了taskExecutor来提交任务,这个时候还需要实现一个Runable的接口来实现具体的任务逻辑。实际上这个过程通过Async注解来进行简化。

Async注解用于表示方法需要异步调用,此时Spring会使用后台的线程池来异步的执行它所注解的方法;一般情况下这个方法的返回类型需要是void的;但也可以是Future类型的;当使用Future时即可对提交的任务执行情况进行判别。

Async注解也可用于类上,当用于类上时,相当于给所有的方法都默认加上了Async注解。

注意使用这个必须在spring Boot中使用Async,EnableAsync,上面configs.java中注释那一行打开,开启异步.

service/AsyncService.java

package com.boot.study.service;

import java.util.concurrent.TimeUnit;

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

@Service
public class AsyncService {

	@Async
	public void hello() {
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		 hello1(); //异步嵌套异步 ,这个异步就不会生效的
		System.out.println("hello aysnc");
	}

	@Async
	public void hello1() {
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("hello1 aysnc");
	}
}

controller/HelloController.java 中应用

package com.boot.study.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.boot.study.service.AsyncService;

@RestController
@RequestMapping("/hello")
public class HelloController {
	@Autowired
	private AsyncService asyncService;

	@GetMapping
	public String hello() {
		asyncService.hello();
		asyncService.hello1();
		return "hello world";
	}
}

解析:

当异步方法中调用异步方法则不生效的.变成了串行

hello1(); //异步嵌套异步 ,这个异步就不会生效的

则上面的页面访问http://localhost/hello时,页面打印hello world,开始执行两个异步方法,两个同时slepp 3s,

asyncService.hello();
asyncService.hello1();

hello1 sleep 3s后立刻输出, 而 hello中的流程是顺序执行,相当于调用了hello1,在sleep 3s,也就是6s后顺序输出

hello1 aysnc
// 6s 后
hello1 aysnc
hello aysnc

Last updated