1、pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.8.BUILD-SNAPSHOT
com.example.task
demo
0.0.1-SNAPSHOT
demo
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-devtools
runtime
true
org.springframework.boot
spring-boot-configuration-processor
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.boot
spring-boot-maven-plugin
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
true
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
true
2、实现
package com.example.task.demo.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author 刘阳洋
* @date 2020/5/17 0017 23:13
*/
@Component
public class SchedulerTask {
private static final SimpleDateFormat f=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
//定时任务注解 5000等于每隔5秒执行一次
@Scheduled(fixedRate = 5000)
public void processFixedRate(){
System.out.println("processFixedRate方式:开始定时任务,现在时间是:"+f.format(new Date()));
}
@Scheduled(cron = "*/5 * * * * ?")
public void processCron(){
System.out.println("processCron:开始定时任务,现在时间是:"+f.format(new Date()));
}
}
3、指定启动参数说明
1、什么是“异步调用”?
“异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;
异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序。
2、同步调用
package com.example.task.demo.task;
import org.springframework.stereotype.Component;
import java.util.Random;
/**
* @author 刘阳洋
* @date 2020/5/17 0017 23:37
*/
@Component
public class Synch {
public static Random random =new Random();
public void doTaskOne() throws Exception {
System.out.println("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
}
public void doTaskTwo() throws Exception {
System.out.println("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
}
public void doTaskThree() throws Exception {
System.out.println("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
}
}
3、异步调用
package com.example.task.demo.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.Random;
import java.util.concurrent.Future;
/**
* @author 刘阳洋
* @date 2020/5/17 0017 23:26
*/
@Component
public class AsyncTask {
public static Random random=new Random();
@Async("myTaskExecutor")
public Future doTaskOne()throws Exception{
System.out.println("开始任务>>>>>>1");
long startTime=System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long endTime=System.currentTimeMillis();
System.out.println("完成任务一消耗的时间:"+(endTime-startTime)+"毫秒");
return new AsyncResult<>("任务一完成");
}
@Async("myTaskExecutor")
public Future doTaskTwo()throws Exception{
System.out.println("开始任务>>>>>>2");
long startTime=System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long endTime=System.currentTimeMillis();
System.out.println("完成任务二消耗的时间:"+(endTime-startTime)+"毫秒");
return new AsyncResult<>("任务二完成");
}
@Async("myTaskExecutor")
public Future doTaskThree()throws Exception{
System.out.println("开始任务>>>>>>3");
long startTime=System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long endTime=System.currentTimeMillis();
System.out.println("完成任务三消耗的时间:"+(endTime-startTime)+"毫秒");
return new AsyncResult<>("任务三完成");
}
}
4、测试
package com.example.task.demo;
import com.example.task.demo.task.AsyncTask;
import com.example.task.demo.task.Synch;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.junit.Test;
import java.util.concurrent.Future;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
private AsyncTask asyncTask;
@Autowired
private Synch synch;
//同步调用测试
@Test
public void testSynch() throws Exception{
synch.doTaskOne();
synch.doTaskTwo();
synch.doTaskThree();
}
//异步调用测试 需要有异步调用返回结果
@Test
public void testAsync() throws Exception{
asyncTask.doTaskOne();
asyncTask.doTaskTwo();
asyncTask.doTaskThree();
Future taskOne=asyncTask.doTaskOne();
Future taskTwo=asyncTask.doTaskTwo();
Future taskThree=asyncTask.doTaskThree();
while (true){
if(taskOne.isDone()&&taskTwo.isDone()&&taskThree.isDone()){
break;
}
Thread.sleep(10000);
}
}
}
5、启动类
package com.example.task.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class DemoApplication {
//异步调用线程池
@Bean("myTaskExecutor")
public Executor myTaskExecutor(){
ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);//核心线程数量,线程池创建时候初始化的线程数
executor.setMaxPoolSize(15);//最大线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setQueueCapacity(200);//缓冲队列,用来缓冲执行任务的队列
executor.setKeepAliveSeconds(60);//当超过了核心线程数之外的线程在空闲时间到达之后会被销毁
executor.setThreadNamePrefix("myTask-");//设置好了之后可以方便我们定位处理任务所在的线程池
executor.setWaitForTasksToCompleteOnShutdown(true);//用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
executor.setAwaitTerminationSeconds(60);//该方法用来设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。
//线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}