1. 应用场景
- 处理log
- 发送邮件、短信
2. 使用步骤
- 在启动类加注解@EnableAsync开启支持
- 定义异步任务类,添加@Component注解
- 异步类中的异步方法加@Async。注意@Async加在类上表示类中所有方法都是异步方法
如:
@SpringBootApplication
@EnableAsync
public class DempProjectApplication {
public static void main(String[] args) {
SpringApplication.run(DempProjectApplication.class, args);
}
}
@Component
public class CustomAsyncTask {
@Async
public void task1() throws InterruptedException {
System.out.println("task1");
Thread.sleep(2000L);
}
@Async
public void task2() throws InterruptedException {
System.out.println("task2");
Thread.sleep(2000L);
}
}
@RestController
@RequestMapping("/api/v1/pub/demo")
public class DemoController {
@Autowired
private CustomAsyncTask task;
@GetMapping("/task")
public JsonData testTask(){
long start = System.currentTimeMillis();
System.out.println("testTask begin ");
task.task1();
task.task2();
long end = System.currentTimeMillis();
System.out.println("testTask end"); // 如果不是异步任务,这里应当花费至少4000ms
return JsonData.buildSuccess("spend " + (end - start));
}
}
测试
@SpringBootTest
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class MockMvcTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testTask() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders
.get("/api/v1/pub/demo/task"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
MockHttpServletResponse resp = mvcResult.getResponse();
String rst = resp.getContentAsString(Charset.forName("utf-8"));
System.out.println(rst);//{"code":0,"msg":null,"data":"spend 6"}
}
}
3. 异步任务使用Future获取结果
注意点:
- 要把异步任务封装到类里面,不能直接写到Controller
- 增加Future 返回结果 AsyncResult(“task执行完成”);
- 如果需要拿到结果 需要判断全部的 task.isDone()
如:
@Component
public class CustomAsyncTask {
@GetMapping("/future")
public JsonData testTaskFuture() {
long start = System.currentTimeMillis();
Future<String> task3 = task.task3();
Future<String> task4 = task.task4();
while (true){
if(task3.isDone() && task4.isDone()){
try {
System.out.println(task3.get());
System.out.println(task4.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}finally {
break;
}
}
}
long end = System.currentTimeMillis();
//正常情况下,这里花费的时间应该至少是4000ms,
//但是task3和task4是异步执行的,虽然get()时会阻塞,但这里最多花费一个任务(以耗时最长的那个为准)的时间
return JsonData.buildSuccess("spend " + (end - start));
}
}
测试:
@SpringBootTest
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class MockMvcTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testFuture() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders
.get("/api/v1/pub/demo/future"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
MockHttpServletResponse resp = mvcResult.getResponse();
String rst = resp.getContentAsString(Charset.forName("utf-8"));
System.out.println(rst);//{"code":0,"msg":null,"data":"spend 2018"}
}
}