Visitar URL original
同步 by ACEis · Pull Request #1 · ACEis/JavaGuide · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
1769 commits
Select commit Hold shift + click to select a range
d5d61b3
[feat]MySQL三大日志(binlog、redo log和undo log)
Snailclimb Aug 15, 2021
b46a3c3
[feat]java9 新特性完善
Snailclimb Aug 16, 2021
814780f
[feat]java10,11 新特性完善
Snailclimb Aug 16, 2021
ef5e010
Merge pull request #1320 from kaka2634/master
Snailclimb Aug 16, 2021
e4bb8f8
[fix]字符串拼接图片修正
Snailclimb Aug 17, 2021
c1b2be0
Update 一文带你看遍JDK9到14的重要新特性.md
Snailclimb Aug 17, 2021
e7e8d48
[feat] Java13新特性重构
Snailclimb Aug 18, 2021
801c220
[feat] Java14新特性重构
Snailclimb Aug 18, 2021
7f853ef
Update zookeeper-plus.md
ObSob Aug 19, 2021
22a16d6
Merge pull request #1326 from ObSob/patch-1
Snailclimb Aug 19, 2021
1bfc5c1
[feat]Java 15 新特性总结
Snailclimb Aug 20, 2021
d535742
Update README.md
Snailclimb Aug 21, 2021
7a16bb8
Update 代理模式详解.md
Aaron-Ge Aug 22, 2021
2cc2d9a
[refractor&feat]数据结构完善&文件夹重构
Snailclimb Aug 23, 2021
fa7ca13
Update java新特性总结.md
Aug 23, 2021
e8cbc06
Update java新特性总结.md
Aug 23, 2021
40a7fcb
Update java新特性总结.md
Aug 23, 2021
46ad9b4
Update linux.md
lllidany Aug 23, 2021
df923e6
Merge pull request #1331 from Aaron-Ge/master
Snailclimb Aug 23, 2021
c8f7777
Merge pull request #1335 from lllidany/master
Snailclimb Aug 23, 2021
a5ce875
Merge pull request #1332 from anaer/patch-1
Snailclimb Aug 23, 2021
d7356a0
Update Java基础知识.md
Aug 24, 2021
c58b5a2
Update Shell.md
Aug 24, 2021
39836b0
Update Shell.md
Aug 24, 2021
d8cae22
Update naming.md
Aug 24, 2021
b55ee4a
Update Spring常见问题总结.md
Aug 24, 2021
e69859b
[feat]修复链接错误
Snailclimb Aug 24, 2021
64fb03b
Update java8-common-new-features.md
Aug 25, 2021
dfda4a4
Update IO模型.md
Aaron-Ge Aug 25, 2021
413e15c
修改布隆过滤器一文链接地址
debugjoker Aug 26, 2021
b5db9e9
跳转链接格式处理
debugjoker Aug 26, 2021
b552b3f
校正
chengcjk Aug 26, 2021
f25a32d
[refractor]移除集合部分内容,单独整理
Snailclimb Aug 26, 2021
a057eda
[feat]Java集合使用注意事项总结
Snailclimb Aug 26, 2021
08e27ac
Merge pull request #1342 from anaer/patch-10
Snailclimb Aug 26, 2021
c1288b8
Merge pull request #1348 from chengcjk/master
Snailclimb Aug 26, 2021
2e1a32b
Merge pull request #1347 from debugjoker/patch-2
Snailclimb Aug 26, 2021
197212b
Merge pull request #1346 from debugjoker/patch-1
Snailclimb Aug 26, 2021
7c23c88
Merge pull request #1345 from Aaron-Ge/master
Snailclimb Aug 26, 2021
8e83b3a
Merge pull request #1339 from anaer/patch-9
Snailclimb Aug 26, 2021
5e2ed4c
Merge pull request #1338 from anaer/patch-8
Snailclimb Aug 26, 2021
6516038
Merge pull request #1337 from anaer/patch-7
Snailclimb Aug 26, 2021
5b3fec4
Merge pull request #1336 from izhengchengjin/patch-1
Snailclimb Aug 26, 2021
c2f10ad
Delete ThreadLocal(未完成).md
Snailclimb Aug 26, 2021
5014c53
Update 如何设计一个亿级网关.md
Aug 27, 2021
c1a239a
补充丢失的文字
Aug 27, 2021
76ef548
错别字
chengcjk Aug 27, 2021
b982a6e
[feat] add 灾备设计&异地多活
Snailclimb Aug 27, 2021
4baeecd
Update [加餐]大白话带你认识JVM.md
liukun2634 Aug 27, 2021
1741a67
Update [加餐]大白话带你认识JVM.md
liukun2634 Aug 27, 2021
06baca5
Merge pull request #1350 from anaer/patch-11
Snailclimb Aug 28, 2021
47aad33
Merge pull request #1352 from chengcjk/master
Snailclimb Aug 28, 2021
3055a04
Merge pull request #1351 from rocky-peng/patch-3
Snailclimb Aug 28, 2021
b4a9f12
Merge pull request #1353 from kaka2634/master
Snailclimb Aug 28, 2021
20cb19b
Update naming.md
Aug 30, 2021
bd6443f
Update JAD反编译tricks.md
Aug 30, 2021
d8be08b
Update JWT优缺点分析以及常见问题解决方案.md
Aug 30, 2021
2e7f5c4
Merge pull request #1354 from anaer/patch-12
Snailclimb Aug 30, 2021
050d306
Merge pull request #1355 from anaer/patch-13
Snailclimb Aug 30, 2021
4656fd9
Merge pull request #1356 from anaer/patch-14
Snailclimb Aug 30, 2021
4189bbe
Update Java集合框架常见面试题.md
Snailclimb Aug 31, 2021
24f27e5
Update RabbitMQ入门看这一篇就够了.md
Aug 31, 2021
bdcd1af
Update IO模型.md
Sep 1, 2021
e534636
Update 代理模式详解.md
Sep 1, 2021
0222e9c
Update BIO,NIO,AIO总结.md
Sep 1, 2021
ffe1c91
Update BIO,NIO,AIO总结.md
Sep 1, 2021
ce6daf1
Create CompletableFuture从入门到实战.md
Snailclimb Sep 1, 2021
4cf77fb
Update 数据库基础知识.md
fengx20 Sep 1, 2021
f0683e5
[feat]CompletableFuture入门
Snailclimb Sep 2, 2021
576e5df
[feat]CompletableFuture入门
Snailclimb Sep 2, 2021
81422c6
Merge pull request #1357 from anaer/patch-16
Snailclimb Sep 2, 2021
f7cc597
Merge pull request #1358 from anaer/patch-17
Snailclimb Sep 2, 2021
a6a0782
Merge pull request #1359 from anaer/patch-18
Snailclimb Sep 2, 2021
d89366f
Merge pull request #1360 from anaer/patch-19
Snailclimb Sep 2, 2021
ec42874
Update RESTfulAPI简明教程.md
Sep 3, 2021
03ba6d7
Merge pull request #1363 from anaer/patch-20
Snailclimb Sep 5, 2021
619be0f
Merge pull request #1361 from fengx20/patch-1
Snailclimb Sep 5, 2021
de32126
Update 万字详解ThreadLocal关键字.md
Sep 6, 2021
7bddf34
Update JDK监控和故障处理工具总结.md
Sep 6, 2021
cc5f281
Update java新特性总结.md
Snailclimb Sep 6, 2021
c656dd8
Update Java基础知识疑难点.md
weixsun Sep 6, 2021
b5b446f
Update 数据库基础知识.md
linzlb Sep 7, 2021
2f974f4
Update Java基础知识.md
Sep 7, 2021
4066882
Update 用好Java中的枚举真的没有那么简单.md
Sep 7, 2021
2e6bf93
Update Spring事务总结.md
weixsun Sep 7, 2021
00422da
Update Spring事务总结.md
weixsun Sep 7, 2021
9b358a9
Update Spring事务总结.md
weixsun Sep 7, 2021
e3da427
Update CAP理论.md
Sep 7, 2021
6842592
Merge pull request #1364 from anaer/patch-21
Snailclimb Sep 7, 2021
376b389
Merge pull request #1365 from anaer/patch-22
Snailclimb Sep 7, 2021
abcd7bf
Merge pull request #1367 from weixsun/Update-Java-基础知识疑难点
Snailclimb Sep 7, 2021
eaf0fb4
Merge pull request #1368 from linzlb/patch-1
Snailclimb Sep 7, 2021
a6abed3
Merge pull request #1369 from anaer/patch-23
Snailclimb Sep 7, 2021
614a292
Merge pull request #1370 from anaer/patch-24
Snailclimb Sep 7, 2021
232ae9b
Merge pull request #1371 from weixsun/Update-Spring事务总结
Snailclimb Sep 7, 2021
545ddee
Merge pull request #1372 from anaer/patch-25
Snailclimb Sep 7, 2021
ada7691
Update README.md
weixsun Sep 7, 2021
7405817
Merge pull request #1373 from weixsun/Update-README
Snailclimb Sep 8, 2021
9f88ccb
Update Git.md
Sep 8, 2021
767f601
Update SpringBoot+Spring常用注解总结.md
Sep 8, 2021
4b87e9b
Merge pull request #1374 from anaer/patch-28
Snailclimb Sep 8, 2021
ac930c3
Merge pull request #1375 from anaer/patch-29
Snailclimb Sep 8, 2021
b9d3148
Update Java8新特性总结.md
Sep 9, 2021
0e2aeec
Update InnoDB对MVCC的实现.md
mo-nian Sep 9, 2021
a975e7d
Merge pull request #1 from mo-nian/mo-nian-patch-1
mo-nian Sep 9, 2021
9fa49af
Update SSO单点登录看这一篇就够了.md
Sep 9, 2021
54df60e
Update bloom-filter.md
Sep 9, 2021
6cdbe28
Update MySQL三大日志.md
ShiqiRao Sep 9, 2021
c9ea539
Update Docker.md
Sep 10, 2021
f077543
Update Docker从入门到实战.md
Sep 10, 2021
a999466
Merge pull request #1376 from anaer/patch-30
Snailclimb Sep 10, 2021
3988950
Merge pull request #1378 from mo-nian/master
Snailclimb Sep 10, 2021
ed6ed0f
Merge pull request #1379 from anaer/patch-31
Snailclimb Sep 10, 2021
8570b57
Merge pull request #1380 from anaer/patch-33
Snailclimb Sep 10, 2021
959753c
Merge pull request #1383 from nockyQ/patch-2
Snailclimb Sep 10, 2021
fb6a0d2
Merge pull request #1384 from anaer/patch-34
Snailclimb Sep 10, 2021
c5e03c7
Merge pull request #1385 from anaer/patch-35
Snailclimb Sep 10, 2021
ff5f4b0
Update Spring常见问题总结.md
huh0ngtao Sep 11, 2021
ffbcf71
Update java线程池学习总结.md
error0g Sep 11, 2021
219a006
Update Spring事务总结.md
error0g Sep 11, 2021
7fed7cc
typo
error0g Sep 11, 2021
44232fc
Update Spring常见问题总结.md
liukun2634 Sep 12, 2021
a7f8dfb
Merge pull request #1387 from hu-asc/master
Snailclimb Sep 13, 2021
a0e826b
Merge pull request #1388 from error0g/error0g-patch-1
Snailclimb Sep 13, 2021
6cc177a
Merge pull request #1390 from error0g/error0g-patch-3
Snailclimb Sep 13, 2021
ba32cba
Merge pull request #1392 from kaka2634/master
Snailclimb Sep 13, 2021
0ebf887
[fix]完全二叉树图片错误修复
Snailclimb Sep 13, 2021
1fdb7f1
[fix]线程池使用不当导致死锁图片修正
Snailclimb Sep 13, 2021
46146f8
[fix]数据可见性算法笔误&内容完善
Snailclimb Sep 13, 2021
c00721e
Update Java集合框架常见面试题.md
Aaron-Ge Sep 13, 2021
d740936
Merge branch 'Snailclimb:master' into master
Aaron-Ge Sep 13, 2021
87d31f1
Merge pull request #1393 from Aaron-Ge/master
Snailclimb Sep 13, 2021
b23da48
Update README.md
Snailclimb Sep 14, 2021
f949397
Update ConcurrentHashMap源码+底层数据结构分析.md
Snailclimb Sep 15, 2021
e4a4e1c
Update 最重要的JVM参数指南.md
Snailclimb Sep 15, 2021
4e2db76
Update Java基础知识.md
gongjixiaobai Sep 16, 2021
f6bbf59
Update 服务之间的调用为啥不直接用HTTP而用RPC.md
Sep 16, 2021
35a7876
Update 服务之间的调用为啥不直接用HTTP而用RPC.md
Sep 16, 2021
b412617
Update Dubbo.md
Sep 16, 2021
8ac6241
Update Kafka常见面试题总结.md
Sep 16, 2021
b0014ac
Update RocketMQ-Questions.md
Sep 16, 2021
90dd5e8
Update RocketMQ.md
Sep 16, 2021
d84f043
Update java新特性总结.md
Snailclimb Sep 16, 2021
225e998
Merge pull request #1398 from gongjixiaobai/patch-1
Snailclimb Sep 16, 2021
628f9e2
Merge pull request #1403 from anaer/patch-42
Snailclimb Sep 16, 2021
9cf981b
Merge pull request #1402 from anaer/patch-41
Snailclimb Sep 16, 2021
a98f58d
Merge pull request #1401 from anaer/patch-39
Snailclimb Sep 16, 2021
af57f15
Merge pull request #1400 from anaer/patch-38
Snailclimb Sep 16, 2021
79bcd3f
Merge pull request #1399 from anaer/patch-36
Snailclimb Sep 16, 2021
fecc256
Update and rename 为什么要网站有哪些常见的网站系统.md to 为什么要网关有哪些常见的网关系统.md
Sep 16, 2021
fba4e83
Merge pull request #1404 from anaer/patch-43
Snailclimb Sep 16, 2021
3edfca4
Update limit-request.md
Sep 17, 2021
f2ef8e4
Update 如何设计一个高可用系统要考虑哪些地方.md
Sep 17, 2021
44cb97c
Update 读写分离&分库分表.md
Sep 17, 2021
53542c4
Update redis-all.md
Qiwenlii Sep 22, 2021
e731a78
fix redis.md bug
Qiwenlii Sep 22, 2021
504e6fa
Merge pull request #1405 from anaer/patch-44
Snailclimb Sep 22, 2021
423a12e
Merge pull request #1406 from anaer/patch-45
Snailclimb Sep 22, 2021
111c224
Merge pull request #1407 from anaer/patch-46
Snailclimb Sep 22, 2021
7ec4dcd
Update Kafka常见面试题总结.md
Snailclimb Sep 22, 2021
1947e5a
[feat]分布式ID文章完善更新
Snailclimb Sep 23, 2021
1bbe22b
Update README.md
Snailclimb Sep 23, 2021
2c1d170
[feat]Java内存区域内容完善补充
Snailclimb Sep 23, 2021
437abe6
Update Java内存区域.md
Snailclimb Sep 23, 2021
dcea444
Update Java内存区域.md
Snailclimb Sep 23, 2021
2996747
[refractor]文件名修改
Snailclimb Sep 24, 2021
b4d29c2
Update java线程池学习总结.md
Snailclimb Sep 24, 2021
66d7c41
Merge pull request #1410 from Qiwenlii/master
Snailclimb Sep 25, 2021
078f4ae
[feat]定时任务
Snailclimb Sep 26, 2021
a2479a7
Update Java并发基础常见面试题总结.md
Snailclimb Sep 26, 2021
08cc656
Update Java并发进阶常见面试题总结.md
Aaron-Ge Sep 26, 2021
83f9e69
Update InnoDB对MVCC的实现.md
hligaty Sep 27, 2021
48e4c18
Update Java集合框架常见面试题.md
debugjoker Sep 27, 2021
302c115
Update Java并发进阶常见面试题总结.md
Aaron-Ge Sep 28, 2021
56d02d2
Update java线程池学习总结.md
Aaron-Ge Sep 28, 2021
3a90b25
Update 拿来即用的线程池最佳实践.md
Aaron-Ge Sep 28, 2021
9211b3e
[feat]首页添加《程序员副业赚钱之路》
Snailclimb Sep 28, 2021
0e7714a
Update README.md
Snailclimb Sep 28, 2021
d4e04d6
Merge pull request #1418 from hligaty/patch-1
Snailclimb Sep 28, 2021
f6e0428
Merge pull request #1420 from debugjoker/patch-3
Snailclimb Sep 28, 2021
eea8a1e
Merge pull request #1417 from Aaron-Ge/master
Snailclimb Sep 28, 2021
e33e785
Update README.md
Snailclimb Sep 28, 2021
e4caa8a
CMS垃圾收集器jvm参数大小写错误
1036956372 Sep 29, 2021
7af2d8a
Merge pull request #1422 from 1036956372/patch-1
Snailclimb Sep 30, 2021
6e77ea0
[feat]api网关重构
Snailclimb Oct 4, 2021
abd8907
Update 堆.md
Masker99 Oct 4, 2021
8023698
Merge pull request #1426 from Masker99/master
Snailclimb Oct 6, 2021
50e2ead
[feat]IntelliJ IDEA 使用指南 | 必备插件推荐 | 插件开发入门 | 重构小技巧 | 源码阅读技巧
Snailclimb Oct 10, 2021
3a6faf3
[feat]字符集详解:为什么不建议在MySQL中使用 utf8 ?
Snailclimb Oct 13, 2021
cbe983e
修改错误字
qiuqianorg Oct 14, 2021
a5b9860
Update README.md
Snailclimb Oct 15, 2021
e3d1c97
Update java线程池学习总结.md
Snailclimb Oct 15, 2021
f6ac89a
Update java线程池学习总结.md
Snailclimb Oct 15, 2021
69a0134
Merge pull request #1428 from SimonLi0427/master
Snailclimb Oct 15, 2021
bd3b9fe
[feat]灾备设计和异地多活文章推荐
Snailclimb Oct 17, 2021
f014952
feat:补充kafka不重复消费的解答
machitaoX Oct 17, 2021
3d92eca
Merge pull request #1431 from machitaoX/feature_completeKafka
Snailclimb Oct 18, 2021
83519ff
Update Kafka常见面试题总结.md
Snailclimb Oct 18, 2021
1ee0f5e
Update README.md
Snailclimb Oct 20, 2021
c1b14de
Update README.md
Snailclimb Oct 24, 2021
81ffbed
[fix]《手把手教你定位常见 Java 性能问题》图片修复
Snailclimb Oct 25, 2021
78857ee
Update README.md
Snailclimb Oct 28, 2021
973f1ee
redis AOF重写描述不准确
xjlgod Nov 1, 2021
8f138f2
Update README.md
Snailclimb Nov 3, 2021
416bb02
装箱和拆箱写反了
xjlgod Nov 4, 2021
f0a7154
Merge branch 'Snailclimb:master' into master
xjlgod Nov 4, 2021
b919dff
Merge pull request #1436 from xjlgod/master
Snailclimb Nov 6, 2021
3dd194a
[feat]内容重构,删除无用文章,优化文件名
Snailclimb Nov 6, 2021
3a5cd7b
Merge branch 'master' of github.com:Snailclimb/JavaGuide
Snailclimb Nov 6, 2021
0ff5f5a
Delete MySQL Index.md
Snailclimb Nov 6, 2021
63bf25b
[feat]Java基础内容重构,删除无用文章,优化文件名
Snailclimb Nov 6, 2021
bb784d4
[feat]Java并发内容重构,删除无用文章,优化文件名
Snailclimb Nov 6, 2021
de3a900
Delete synchronized在JDK1.6之后的底层优化.md
Snailclimb Nov 6, 2021
47b7c85
[feat]jvm内容重构,删除无用文章,优化文件名
Snailclimb Nov 7, 2021
a26ff09
Delete submission.html
Snailclimb Nov 7, 2021
23efacc
Update java集合框架基础知识&面试题总结.md
Snailclimb Nov 7, 2021
dc45389
[feat]🔥 基于 vuepress 重构整个项目,提升阅读体验
Snailclimb Nov 9, 2021
3916409
[feat]网站首页更新
Snailclimb Nov 9, 2021
25b0f2b
[feat]在线阅读网站样式完善
Snailclimb Nov 9, 2021
cbfb2c5
[feat]文章名规范&在线阅读完善样式美化
Snailclimb Nov 9, 2021
06f726f
Update readme.md
Snailclimb Nov 9, 2021
a66506d
fix typos
Casflawed Nov 9, 2021
9dd6f54
Merge branch 'Snailclimb:master' into flameking_work-A
Casflawed Nov 9, 2021
afc837a
Update .gitignore
Snailclimb Nov 9, 2021
537fdce
Create .gitattributes
Snailclimb Nov 9, 2021
6f5aeb1
Merge branch 'Snailclimb:master' into flameking_work-A
Casflawed Nov 9, 2021
bd2f4ef
fix typos
Casflawed Nov 9, 2021
91ccfe3
[文件名更正]
Snailclimb Nov 10, 2021
2a78961
Update readme.md
Snailclimb Nov 10, 2021
b87ef11
Merge branch 'Snailclimb:master' into flameking_work-A
Casflawed Nov 10, 2021
351ea31
[fix]图片错误修复
Snailclimb Nov 10, 2021
47a6b08
Update README.md
Snailclimb Nov 10, 2021
e9b4a0c
fix typos
Casflawed Nov 10, 2021
405dec3
[feat]百度统计
Snailclimb Nov 10, 2021
e7b509e
fix typos
Casflawed Nov 10, 2021
e0cd0a3
Merge branch 'Snailclimb:master' into flameking_work-A
Casflawed Nov 10, 2021
d0a5502
[fix]百度统计
Snailclimb Nov 10, 2021
580617f
Merge branch 'Snailclimb:master' into flameking_work-A
Casflawed Nov 10, 2021
78d1cb4
Merge pull request #1444 from acflameking/flameking_work-A
Snailclimb Nov 10, 2021
a2f9479
Update config.js
Snailclimb Nov 10, 2021
63e8ee6
Update 手把手教你定位常见Java性能问题.md
Snailclimb Nov 10, 2021
1543c0d
Update 操作系统常见面试题&知识点总结.md
Aaron-Ge Nov 10, 2021
c0cdd9f
Update 操作系统常见面试题&知识点总结.md
Aaron-Ge Nov 11, 2021
7e718d5
修改错误字
qiuqianorg Nov 13, 2021
e878f58
Merge pull request #1446 from Aaron-Ge/master
Snailclimb Nov 16, 2021
8965fcd
Merge pull request #1448 from qiuqianorg/master
Snailclimb Nov 16, 2021
b54c726
修改错别字
cliveyuan Mar 9, 2022
77260e6
Merge pull request #1605 from cliveyuan/patch-1
Snailclimb Mar 12, 2022
fb6e11b
修改错别字
Mar 20, 2022
98eafbd
Merge pull request #1631 from drlifeL/master
Snailclimb Mar 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[feat]定时任务
  • Loading branch information
Snailclimb committed Sep 26, 2021
commit 078f4aec25d9c6fdd34ad6771f08ae771bca56e5
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle

数据脱敏说的就是我们根据特定的规则对敏感信息数据进行变形,比如我们把手机号、身份证号某些位数使用 * 来代替。

### 定时任务

最近有朋友问到定时任务相关的问题。于是,我简单写了一篇文章总结一下定时任务的一些概念以及一些常见的定时任务技术选型:[《Java定时任务大揭秘》](./docs/system-design/Java定时任务大揭秘.md)

### 分布式

#### CAP 理论和 BASE 理论
Expand Down Expand Up @@ -285,7 +289,7 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读:
1. [ 大白话入门 Spring Cloud](docs/system-design/micro-service/spring-cloud.md)
2. [微服务/分布式大厂真实面试问题解答](https://xiaozhuanlan.com/topic/2895047136)

### 高并发
### 高性能

#### 消息队列

Expand Down
317 changes: 317 additions & 0 deletions docs/system-design/Java定时任务大揭秘.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
## 为什么需要定时任务?

我们来看一下几个非常常见的业务场景:

1. 某系统凌晨要进行数据备份。
2. 某电商平台,用户下单半个小时未支付的情况下需要自动取消订单。
3. 某媒体聚合平台,每 10 分钟动态抓取某某网站的数据为自己所用。
4. 某博客平台,支持定时发送文章。
5. 某基金平台,每晚定时计算用户当日收益情况并推送给用户最新的数据。
6. ......

这些场景往往都要求我们在某个特定的时间去做某个事情。

## 单机定时任务技术选型

### Timer

`java.util.Timer`是 JDK 1.3 开始就已经支持的一种定时任务的实现方式。

`Timer` 内部使用一个叫做 `TaskQueue` 的类存放定时任务,它是一个基于最小堆实现的优先级队列。`TaskQueue` 会按照任务距离下一次执行时间的大小将任务排序,保证在堆顶的任务最先执行。这样在需要执行任务时,每次只需要取出堆顶的任务运行即可!

`Timer` 使用起来比较简单,通过下面的方式我们就能创建一个 1s 之后执行的定时任务。

```java
// 示例代码:
TimerTask task = new TimerTask() {
public void run() {
System.out.println("当前时间: " + new Date() + "n" +
"线程名称: " + Thread.currentThread().getName());
}
};
System.out.println("当前时间: " + new Date() + "n" +
"线程名称: " + Thread.currentThread().getName());
Timer timer = new Timer("Timer");
long delay = 1000L;
timer.schedule(task, delay);


//输出:
当前时间: Fri May 28 15:18:47 CST 2021n线程名称: main
当前时间: Fri May 28 15:18:48 CST 2021n线程名称: Timer
```

不过其缺陷较多,比如一个 `Timer` 一个线程,这就导致 `Timer` 的任务的执行只能串行执行,一个任务执行时间过长的话会影响其他任务(性能非常差),再比如发生异常时任务直接停止(`Timer` 只捕获了 `InterruptedException` )。

`Timer` 类上的有一段注释是这样写的:

```JAVA
* This class does not offer real-time guarantees: it schedules
* tasks using the <tt>Object.wait(long)</tt> method.
*Java 5.0 introduced the {@code java.util.concurrent} package and
* one of the concurrency utilities therein is the {@link
* java.util.concurrent.ScheduledThreadPoolExecutor
* ScheduledThreadPoolExecutor} which is a thread pool for repeatedly
* executing tasks at a given rate or delay. It is effectively a more
* versatile replacement for the {@code Timer}/{@code TimerTask}
* combination, as it allows multiple service threads, accepts various
* time units, and doesn't require subclassing {@code TimerTask} (just
* implement {@code Runnable}). Configuring {@code
* ScheduledThreadPoolExecutor} with one thread makes it equivalent to
* {@code Timer}.
```

大概的意思就是: `ScheduledThreadPoolExecutor` 支持多线程执行定时任务并且功能更强大,是 `Timer` 的替代品。

### ScheduledExecutorService

`ScheduledExecutorService` 是一个接口,有多个实现类,比较常用的是 `ScheduledThreadPoolExecutor` 。

![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/20210607154324712.png)

`ScheduledThreadPoolExecutor` 本身就是一个线程池,支持任务并发执行。并且,其内部使用 `DelayQueue` 作为任务队列。

```java
// 示例代码:
TimerTask repeatedTask = new TimerTask() {
@SneakyThrows
public void run() {
System.out.println("当前时间: " + new Date() + "n" +
"线程名称: " + Thread.currentThread().getName());
}
};
System.out.println("当前时间: " + new Date() + "n" +
"线程名称: " + Thread.currentThread().getName());
ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
long delay = 1000L;
long period = 1000L;
executor.scheduleAtFixedRate(repeatedTask, delay, period, TimeUnit.MILLISECONDS);
Thread.sleep(delay + period * 5);
executor.shutdown();
//输出:
当前时间: Fri May 28 15:40:46 CST 2021n线程名称: main
当前时间: Fri May 28 15:40:47 CST 2021n线程名称: pool-1-thread-1
当前时间: Fri May 28 15:40:48 CST 2021n线程名称: pool-1-thread-1
当前时间: Fri May 28 15:40:49 CST 2021n线程名称: pool-1-thread-2
当前时间: Fri May 28 15:40:50 CST 2021n线程名称: pool-1-thread-2
当前时间: Fri May 28 15:40:51 CST 2021n线程名称: pool-1-thread-2
当前时间: Fri May 28 15:40:52 CST 2021n线程名称: pool-1-thread-2
```

不论是使用 `Timer` 还是 `ScheduledExecutorService` 都无法使用 Cron 表达式指定任务执行的具体时间。

### Spring Task

![](https://img-blog.csdnimg.cn/20210528145056880.png)

我们直接通过 Spring 提供的 `@Scheduled` 注解即可定义定时任务,非常方便!

```java
/**
* cron:使用Cron表达式。 每分钟的1,2秒运行
*/
@Scheduled(cron = "1-2 * * * * ? ")
public void reportCurrentTimeWithCronExpression() {
log.info("Cron Expression: The time is now {}", dateFormat.format(new Date()));
}

```

我在大学那会做的一个 SSM 的企业级项目,就是用的 Spring Task 来做的定时任务。

并且,Spring Task 还是支持 **Cron 表达式** 的。Cron 表达式主要用于定时作业(定时任务)系统定义执行时间或执行频率的表达式,非常厉害,你可以通过 Cron 表达式进行设置定时任务每天或者每个月什么时候执行等等操作。咱们要学习定时任务的话,Cron 表达式是一定是要重点关注的。推荐一个在线 Cron 表达式生成器:[http://cron.qqe2.com/](http://cron.qqe2.com/) 。

但是,Spring 自带的定时调度只支持单机,并且提供的功能比较单一。之前写过一篇文章:[《5 分钟搞懂如何在 Spring Boot 中 Schedule Tasks》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485563&idx=1&sn=7419341f04036a10b141b74624a3f8c9&chksm=cea247b0f9d5cea6440759e6d49b4e77d06f4c99470243a10c1463834e873ca90266413fbc92&token=2133161636&lang=zh_CN#rd) ,不了解的小伙伴可以参考一下。

Spring Task 底层是基于 JDK 的 `ScheduledThreadPoolExecutor` 线程池来实现的。

**优缺点总结:**

- 优点: 简单,轻量,支持 Cron 表达式
- 缺点 :功能单一

### 时间轮

Kafka、Dubbo、ZooKeeper、Netty 、Caffeine 、Akka 中都有对时间轮的实现。

时间轮简单来说就是一个环形的队列(底层一般基于数组实现),队列中的每一个元素(时间格)都可以存放一个定时任务列表。

时间轮中的每个时间格代表了时间轮的基本时间跨度或者说时间精度,加入时间一秒走一个时间格的话,那么这个时间轮的最高精度就是 1 秒(也就是说 3 s 和 3.9s 会在同一个时间格中)。

下图是一个有 12 个时间格的时间轮,转完一圈需要 12 s。当我们需要新建一个 3s 后执行的定时任务,只需要将定时任务放在下标为 3 的时间格中即可。当我们需要新建一个 9s 后执行的定时任务,只需要将定时任务放在下标为 9 的时间格中即可。

![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/20210607171334861.png)

那当我们需要创建一个 13s 后执行的定时任务怎么办呢?这个时候可以引入一叫做 **圈数/轮数** 的概念,也就是说这个任务还是放在下标为 3 的时间格中, 不过它的圈数为 2 。

除了增加圈数这种方法之外,还有一种 **多层次时间轮** (类似手表),Kafka 采用的就是这种方案。

针对下图的时间轮,我来举一个例子便于大家理解。

![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/20210607193042151.png)

上图的时间轮,第 1 层的时间精度为 1 ,第 2 层的时间精度为 20 ,第 3 层的时间精度为 400。假如我们需要添加一个 350s 后执行的任务 A 的话(当前时间是 0s),这个任务会被放在第 2 层(因为第二层的时间跨度为 20\*20=400>350)的第 350/20=17 个时间格子。

当第一层转了 17 圈之后,时间过去了 340s ,第 2 层的指针此时来到第 17 个时间格子。此时,第 2 层第 17 个格子的任务会被移动到第 1 层。

任务 A 当前是 10s 之后执行,因此它会被移动到第 1 层的第 10 个时间格子。

这里在层与层之间的移动也叫做时间轮的升降级。参考手表来理解就好!

![](https://img-blog.csdnimg.cn/20210607195206797.png)

**时间轮比较适合任务数量比较多的定时任务场景,它的任务写入和执行的时间复杂度都是 0(1)。**

## 分布式定时任务技术选型

上面提到的一些定时任务的解决方案都是在单机下执行的,适用于比较简单的定时任务场景比如每天凌晨备份一次数据。

如果我们需要一些高级特性比如支持任务在分布式场景下的分片和高可用的话,我们就需要用到分布式任务调度框架了。

通常情况下,一个定时任务的执行往往涉及到下面这些角色:

- **任务** : 首先肯定是要执行的任务,这个任务就是具体的业务逻辑比如定时发送文章。
- **调度器** :其次是调度中心,调度中心主要负责任务管理,会分配任务给执行器。
- **执行器** : 最后就是执行器,执行器接收调度器分派的任务并执行。

### Quartz

![](https://img-blog.csdnimg.cn/2021052814502425.png)

一个很火的开源任务调度框架,完全由`Java`写成。`Quartz` 可以说是 Java 定时任务领域的老大哥或者说参考标准,其他的任务调度框架基本都是基于 `Quartz` 开发的,比如当当网的`elastic-job`就是基于`quartz`二次开发之后的分布式调度解决方案。

使用 `Quartz` 可以很方便地与 `Spring` 集成,并且支持动态添加任务和集群。但是,`Quartz` 使用起来也比较麻烦,API 繁琐。

并且,`Quzrtz` 并没有内置 UI 管理控制台,不过你可以使用 [quartzui](https://github.com/zhaopeiym/quartzui) 这个开源项目来解决这个问题。

另外,`Quartz` 虽然也支持分布式任务。但是,它是在数据库层面,通过数据库的锁机制做的,有非常多的弊端比如系统侵入性严重、节点负载不均衡。有点伪分布式的味道。

**优缺点总结:**

- 优点: 可以与 `Spring` 集成,并且支持动态添加任务和集群。
- 缺点 :分布式支持不友好,没有内置 UI 管理控制台、使用麻烦(相比于其他同类型框架来说)

### Elastic-Job

![](https://img-blog.csdnimg.cn/20210528144508114.png)

`Elastic-Job` 是当当网开源的一个基于`Quartz`和`ZooKeeper`的分布式调度解决方案,由两个相互独立的子项目 `Elastic-Job-Lite` 和 `Elastic-Job-Cloud` 组成,一般我们只要使用 `Elastic-Job-Lite` 就好。

`ElasticJob` 支持任务在分布式场景下的分片和高可用、任务可视化管理等功能。

![](https://img-blog.csdnimg.cn/20210608080437356.png)

ElasticJob-Lite 的架构设计如下图所示:

![](https://oscimg.oschina.net/oscnet/up-a8f63f828666d43009d5d3497bcbd2cfb61.png)

从上图可以看出,`Elastic-Job` 没有调度中心这一概念,而是使用 `ZooKeeper` 作为注册中心,注册中心负责协调分配任务到不同的节点上。

Elastic-Job 中的定时调度都是由执行器自行触发,这种设计也被称为去中心化设计(调度和处理都是执行器单独完成)。

```java
@Component
@ElasticJobConf(name = "dayJob", cron = "0/10 * * * * ?", shardingTotalCount = 2,
shardingItemParameters = "0=AAAA,1=BBBB", description = "简单任务", failover = true)
public class TestJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
log.info("TestJob任务名:【{}】, 片数:【{}】, param=【{}】", shardingContext.getJobName(), shardingContext.getShardingTotalCount(),
shardingContext.getShardingParameter());
}
}
```

**相关地址:**

- Github 地址:https://github.com/apache/shardingsphere-elasticjob。
- 官方网站:https://shardingsphere.apache.org/elasticjob/index_zh.html 。

**优缺点总结:**

- 优点 :可以与 `Spring` 集成、支持分布式、支持集群、性能不错
- 缺点 :依赖了额外的中间件比如 Zookeeper(复杂度增加,可靠性降低、维护成本变高)

### XXL-JOB

![](https://img-blog.csdnimg.cn/20210528144611728.png)

`XXL-JOB` 于 2015 年开源,是一款优秀的轻量级分布式任务调度框架,支持任务可视化管理、弹性扩容缩容、任务失败重试和告警、任务分片等功能,

![](https://img-blog.csdnimg.cn/20210608080550433.png)

根据 `XXL-JOB` 官网介绍,其解决了很多 `Quartz` 的不足。

![](https://img-blog.csdnimg.cn/20210607202503193.png)

`XXL-JOB` 的架构设计如下图所示:

![](https://oscimg.oschina.net/oscnet/up-b8ecc6acf651f112c4dfae98243d72adea3.png)

从上图可以看出,`XXL-JOB` 由 **调度中心** 和 **执行器** 两大部分组成。调度中心主要负责任务管理、执行器管理以及日志管理。执行器主要是接收调度信号并处理。另外,调度中心进行任务调度时,是通过自研 RPC 来实现的。

不同于 `Elastic-Job` 的去中心化设计, `XXL-JOB` 的这种设计也被称为中心化设计(调度中心调度多个执行器执行任务)。

和 `Quzrtz` 类似 `XXL-JOB` 也是基于数据库锁调度任务,存在性能瓶颈。不过,一般在任务量不是特别大的情况下,没有什么影响的,可以满足绝大部分公司的要求。

不要被 `XXL-JOB` 的架构图给吓着了,实际上,我们要用 `XXL-JOB` 的话,只需要重写 `IJobHandler` 自定义任务执行逻辑就可以了,非常易用!

```java
@JobHandler(value="myApiJobHandler")
@Component
public class MyApiJobHandler extends IJobHandler {

@Override
public ReturnT<String> execute(String param) throws Exception {
//......
return ReturnT.SUCCESS;
}
}
```

还可以直接基于注解定义任务。

```java
@XxlJob("myAnnotationJobHandler")
public ReturnT<String> myAnnotationJobHandler(String param) throws Exception {
//......
return ReturnT.SUCCESS;
}
```

![](https://img-blog.csdnimg.cn/20210607200728212.png)

**相关地址:**

- Github 地址:https://github.com/xuxueli/xxl-job/。
- 官方介绍:https://www.xuxueli.com/xxl-job/ 。

**优缺点总结:**

- 优点:开箱即用(学习成本比较低)、与 Spring 集成、支持分布式、支持集群、内置了 UI 管理控制台。
- 缺点:不支持动态添加任务(如果一定想要动态创建任务也是支持的,参见:[xxl-job issue277](https://github.com/xuxueli/xxl-job/issues/277))。

### PowerJob

![](https://img-blog.csdnimg.cn/20210528145009701.png)

非常值得关注的一个分布式任务调度框架,分布式任务调度领域的新星。目前,已经有很多公司接入比如 OPPO、京东、中通、思科。

这个框架的诞生也挺有意思的,PowerJob 的作者当时在阿里巴巴实习过,阿里巴巴那会使用的是内部自研的 SchedulerX(阿里云付费产品)。实习期满之后,PowerJob 的作者离开了阿里巴巴。想着说自研一个 SchedulerX,防止哪天 SchedulerX 满足不了需求,于是 PowerJob 就诞生了。

更多关于 PowerJob 的故事,小伙伴们可以去看看 PowerJob 作者的视频 [《我和我的任务调度中间件》](https://www.bilibili.com/video/BV1SK411A7F3/)。简单点概括就是:“游戏没啥意思了,我要扛起了新一代分布式任务调度与计算框架的大旗!”。

由于 SchedulerX 属于人民币产品,我这里就不过多介绍。PowerJob 官方也对比过其和 QuartZ、XXL-JOB 以及 SchedulerX。

![](https://oscimg.oschina.net/oscnet/up-795f5e9b0d875063717b1ee6a08f2ff1c01.png)

## 总结

这篇文章中,我主要介绍了:

- **定时任务的相关概念** :为什么需要定时任务、定时任务中的核心角色、分布式定时任务。
- **定时任务的技术选型** : XXL-JOB 2015 年推出,已经经过了很多年的考验。XXL-JOB 轻量级,并且使用起来非常简单。虽然存在性能瓶颈,但是,在绝大多数情况下,对于企业的基本需求来说是没有影响的。PowerJob 属于分布式任务调度领域里的新星,其稳定性还有待继续考察。ElasticJob 由于在架构设计上是基于 Zookeeper ,而 XXL-JOB 是基于数据库,性能方面的话,ElasticJob 略胜一筹。

这篇文章并没有介绍到实际使用,但是,并不代表实际使用不重要。我在写这篇文章之前,已经动手写过相应的 Demo。像 Quartz,我在大学那会就用过。不过,当时用的是 Spring 。为了能够更好地体验,我自己又在 Spring Boot 上实际体验了一下。如果你并没有实际使用某个框架,就直接说它并不好用的话,是站不住脚的。

最后,这篇文章要感谢艿艿的帮助,写这篇文章的时候向艿艿询问过一些问题。推荐一篇艿艿写的偏实战类型的硬核文章:[《Spring Job?Quartz?XXL-Job?年轻人才做选择,艿艿全莽~》](https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&mid=2247490679&idx=1&sn=25374dbdcca95311d41be5d7b7db454d&chksm=fa4963c6cd3eead055bb9cd10cca13224bb35d0f7373a27aa22a55495f71e24b8273a7603314&scene=27#wechat_redirect) 。