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