在前一实现数据的抓取:OkHttp3中,获得了想要的数据。但是 ,由于目标数据是实时更新的,所以需要实时获取。
本文介绍了四种定时任务:Timer
、ScheduledExecutorService
、Spring Task
、Quartz
一、Timer
- 博文链接:定时器Timer
- 同样的,自己测试了一个简单的demo
public class Test {
public static void main(String[] args) throws ParseException {
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("运行了,现在" + new Date());
}
};
timer.schedule(timerTask, 3000,3000);
}
}
安装了 Alibaba Java Coding Guidelines
的插件之后,他会报出预警:
二、 ScheduledExecutorService
定时任务和线程池功能结合,能够更好的处理java中的一些并发的任务需要。
两种最常用的调度方法
- ScheduleAtFixedRate
- ScheduleWithFixedDelay
1. 创建任务
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @apiNote
* @date: 2021/9/16 16:15
*/
public class MyScheduledExecutor implements Runnable {
public void run() {
//创建时间格式,精确到毫秒
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS");
//打印开始执行的系统时间
System.out.println(sdf.format(new Date()));
//执行任务的主要部分,打印100w个空字符串,耗时比较长
for (int i = 0; i < 100000000; i++) {
System.out.print("");
}
//打印结束执行的系统时间
System.out.println(sdf.format(new Date()));
//与下次执行的结果分割开
System.out.println("=============================");
}
}
2. 执行scheduleAtFixedRate()方法
按照固定的节奏安排任务
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author hanyulin
* @apiNote
* @date: 2021/9/9 16:21
*/
public class Test {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 延迟10之后的任务开始执行
long initialDelay = 10;
// 连续执行任务之间的时间:20
// 即:上一次开始的时间与下一次开始的时间的间隔
// 如果任务执行一次的时间超过了period,下次任务会紧随上次任务的结束而开始执行。
long period = 20;
service.scheduleAtFixedRate(new MyScheduledExecutor(), initialDelay, period, TimeUnit.SECONDS);
// service.scheduleWithFixedDelay(new MyScheduledExecutor(), initialDelay, period, TimeUnit.SECONDS);
}
}
控制台打印的结果如下:
2021-09-16 17:17:05:782
2021-09-16 17:17:14:300
=============================
2021-09-16 17:17:25:670
2021-09-16 17:17:34:442
=============================
2021-09-16 17:17:45:669
2021-09-16 17:17:54:513
=============================
2021-09-16 17:18:05:671
2021-09-16 17:18:14:525
=============================
2021-09-16 17:18:25:672
就类似于,老板指派了你明天(initialDelay = 1天 )的任务:定时每天(period = 1天)去安装硬件。第二天到了,你就开始干活。
- 情景一:如果你干的快,3小时干完了,那么,今天得其他小时你就可以摸鱼了,等到第二天任务开始,你就又开始工作。
- 情景二:要是任务其实得两天才能够把预计1天的硬件安装完成,远大于预估期(period = 1天)。那么你就会休息都不休息,做完了还得做(即:下次任务会紧随上次任务的结束而开始执行)。如下图:
3. 执行scheduleWithFixedDelay方法
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 延迟10之后的任务开始执行
long initialDelay = 10;
// 连续执行任务之间的时间:20 即:上一次结束的时间与下一次开始的时间的间隔
// 如果任务执行一次的时间超过了period,下次任务在上次任务的结束时间后的20而开始执行。
long period = 20;
service.scheduleWithFixedDelay(new MyScheduledExecutor(), initialDelay, period, TimeUnit.SECONDS);
}
控制台打印的结果如下:
2021-09-16 17:40:05:105
2021-09-16 17:40:13:257
=============================
2021-09-16 17:40:33:265
2021-09-16 17:40:41:610
=============================
2021-09-16 17:41:01:618
2021-09-16 17:41:10:520
=============================
2021-09-16 17:41:30:524
2021-09-16 17:41:39:246
=============================
2021-09-16 17:41:59:255
2021-09-16 17:42:08:54
就类似于,老板指派了你明天(initialDelay = 1天 )的任务:不管做完的时间长短,做完之后定时休息了(period = 1天)再去安装硬件。
三、Spring Task
1. yml文件配置Redis
- 把实时抓取到的数据放到Redis里面进行实时更新
- 这样在执行这个请求的时候,就能够保证数据的时效性
spring:
redis:
host: 127.0.0.1 # redis地址
port: 6379 # redis端口号
database: 0
lettuce:
pool:
min-idle: 1
max-active: 3
max-idle: 2
max-wait: -1ms
time-between-eviction-runs: 100000
2. 启动类上添加注解@EnableScheduling
@SpringBootApplication
@EnableScheduling
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication .class, args);
}
}
3. 创建任务
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.weixin.login.FilDTO;
import com.weixin.login.util.OkHttp3Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Map;
/**
* @author helen
* @apiNote
* @date: 2021/9/10 15:09
*/
@Component
public class FilJob {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Scheduled(cron = "*/5 * * * * ?")
// cron表达式 http://qqe2.com/cron/index
public void filJob() {
String result = OkHttp3Util.send("https://api.filscout.com/api/v1/network/overview/info", null, OkHttp3Util.GET, null);
if (result != null) {
Map map = JSONUtil.toBean(result, Map.class);
JSONObject data = (JSONObject) map.get("data");
Map<String, Object> linkedTreeMap = JSONUtil.toBean(data, Map.class);
FilDTO filDTO = new FilDTO();
filDTO.setActiveMiners((Integer) linkedTreeMap.get("activeMiners"));
filDTO.setBlockRewardIn24h((BigDecimal) linkedTreeMap.get("blockRewardIn24h"));
filDTO.setNewlyFilIn24h((BigDecimal) linkedTreeMap.get("newlyFilIn24h"));
filDTO.setOneDayMessages((Integer) linkedTreeMap.get("oneDayMessages"));
filDTO.setPowerIn24H((String) linkedTreeMap.get("PowerIn24H"));
filDTO.setTransferIn24H((Integer) linkedTreeMap.get("transferIn24H"));
stringRedisTemplate.boundValueOps("filDTO").set(JSONUtil.toJsonStr(filDTO));
}
}
}
4. TestController
import com.google.gson.Gson;
import com.weixin.login.FilDTO;
import com.weixin.login.vo.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author hanyulin
* @apiNote
* @date: 2021/9/11 11:31
*/
@RestController
@Api(tags = "测试")
public class TestController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@ApiOperation("抓取数据")
@GetMapping(value = "/test")
public R<FilDTO> test() {
String filString = stringRedisTemplate.boundValueOps("filDTO").get();
FilDTO filDTO = new Gson().fromJson(filString, FilDTO.class);
return new R<>().ok(filDTO);
}
}
5. 结果
四、Quartz
[定时任务框架Quartz]