任务调度(Quartz):
在某个时间点执行某项任务,需要定义事件规则,并且学习一套cron表达式。
cron表达式由6-7位数字或者字母组成的一个字符串,中间用空格隔开。
空格表示在准确的时间点执行一次任务。
“-”表示在某个事件段之间执行一次任务。
“/”表示每隔一段时间执行一次任务。
“,”表示在某几个时间点执行一次任务。
“*”表示在这个单位内的每一刻(例如:每时每分每秒)执行一次任务。
6-7位克隆表达式:(其中日期和星期两者只可存在其一,不能要求星期一的同时又要求几月几号,这不符合逻辑)。星期(1-7)中:1代表周日。
“L”表示最大值。
"?"代表占位符,通常在日期和星期间会出现。
“#”表示第几个。
使用场景
在设定的时间内发送固定的短信。
在启动类中中配置@EnableScheduling注解。
@EnableScheduling:开启定时任务功能。
创建一个类负责发送信息。
我设置的是的是每天下午三点15分发送信息。
@component表示将这个类交给Spring管理,由于不知道是哪个类,所以用@component注解。
@Scheduled标记要调度的方法的注解,必须要指定cron。
异步任务
比如说公司团建,准备吃龙虾,我派三个人出去买东西,一个人负责买龙虾,一个人负责买锅,一个人负责买调料,每个人花时5秒。如果不使用异步任务,每个人都要花费五秒,最后需要15秒的时间才可完成烧制龙虾的操作。代码如下:
创建一个控制器进行烧制龙虾操作。
开启异步调用之后,代码如下:
在启动类配置异步调用的注解。
@EnableAsync 注解启用了 Spring 异步方法执行功能。
在每个子线程的方法上添加@Async注解
@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者 无需等待它的完成,即可继续其他的操作。
这时候在页面中运行会直接得到响应结果。
并且总用时为0秒。
这是因为我的每个方法都是通过子线程去完成的,我的主线程上并没有任何的方法,所以主线程可以直接得到响应的结果,用时为0秒。
以上只能解决我的第一个问题:三个人同时出去买东西了。
但是我需要等三个线程全部执行完毕才能进行烧制龙虾的操作。
此时需要CountDownLatch类来完成。
CountDownLatch
CountDownLatch是一个一次性的类,计数器不能被重置。可以使一个或多个线程等待其他各个线程执行完毕后在执行。
操作如下:
将子线程所有方法的返回值改为Future<String>类型。
Future<String>:在子线程中被调用,同时它有返回值,只有将加载的数据直接return出来就好。
下图中的代码返回的是一个异步的结果。
此刻控制器中调用子线程方法的步骤都有了返回的结果。
用死循环将每个线程上锁,只有当三个子线程全部执行完毕才可解锁。
为了让结果看的更明显,可以将三个字线程所花费的时间改成各不相同的数字。
运行查看结果。
可以看到,总用时取的是子线程中用时最多的。
以上就是异步任务。
异步任务通常可以靠创建一个子线程来运行方法代码,在SpringBoot中可以同@Async注解达到同样效果。
多线程并行和并发
并发:同一时间内,很多的请求涌进来,执行某个方法。
并行:一个请求,在执行某个方法时,会存在多个线程执行任务。
通常会靠子线程去运行一些较为耗时的操作。