好网站你知道企业网站建设英文
好网站你知道,企业网站建设英文,2023中关村手机排行榜,搜索优化软件一、XXLJOB 时间轮#xff08;TimeWheel#xff09;核心原理1. 为什么要用时间轮#xff1f;
XXLJOB 作为分布式任务调度框架#xff0c;需要高效管理大量定时/周期性任务#xff08;如每秒触发上千个任务#xff09;。传统的「定时线程池#xff08;ScheduledExecutorS…一、XXLJOB 时间轮TimeWheel核心原理1. 为什么要用时间轮XXLJOB 作为分布式任务调度框架需要高效管理大量定时/周期性任务如每秒触发上千个任务。传统的「定时线程池ScheduledExecutorService」在任务量巨大时会出现以下问题线程池频繁创建/销毁线程性能开销大任务触发时间分散线程切换成本高无法高效支持「秒级/分钟级」的粗粒度调度。时间轮的核心优势批量调度将相同时间维度的任务归到同一“槽位”批量触发减少线程切换时间复杂度O(1)任务的添加/删除/触发均为常数时间支持海量任务低资源消耗仅需少量线程通常1个驱动时间轮转动无需为每个任务创建线程。2. 时间轮的核心概念XXL-Job 实现XXL-Job 的时间轮是分层时间轮简化版核心结构概念说明时间槽Slot时间轮的最小刻度单元如1秒每个槽位存放该时刻需要触发的任务列表轮盘大小时间轮的槽位总数如60个槽 → 覆盖1分钟当前指针指向当前时间对应的槽位每秒/每分向前移动一格任务链表每个槽位挂载一个任务链表指针移动到该槽时遍历执行所有任务分层降级若任务触发时间超过当前轮盘范围如70秒后先放入“分钟级”轮盘到点后降级到“秒级”轮盘二、XXL-Job 时间轮核心实现代码XXL-Job 的时间轮核心在JobScheduleHelper类中以下是简化版核心代码保留核心逻辑与源码对齐importjava.util.*;importjava.util.concurrent.*;importjava.util.concurrent.atomic.AtomicInteger;/** * XXL-Job 时间轮核心实现简化版 */publicclassXxlJobTimeWheel{// 时间轮核心配置 // 时间槽大小单位毫秒XXL-Job 默认1秒1000msprivatestaticfinallongTICK_MS1000;// 时间轮槽位数量默认60个 → 覆盖60秒privatestaticfinalintWHEEL_SIZE60;// 时间轮总跨度60*100060秒privatestaticfinallongWHEEL_RANGETICK_MS*WHEEL_SIZE;// 时间轮核心结构 // 时间槽数组每个槽位对应一个任务链表privatefinalListLinkedListScheduleJobtimeWheelSlotsnewArrayList(WHEEL_SIZE);// 时间轮当前指针指向当前槽位privatefinalAtomicIntegercurrentPosnewAtomicInteger(0);// 驱动时间轮转动的线程池仅1个线程privatefinalScheduledExecutorServicescheduledExecutorServiceExecutors.newSingleThreadScheduledExecutor(r-{ThreadthreadnewThread(r);thread.setName(xxl-job-timewheel-driver);thread.setDaemon(true);// 守护线程不阻塞JVM退出returnthread;});// 待调度的任务模型publicstaticclassScheduleJob{privateintjobId;// 任务IDprivatelongtriggerTime;// 任务触发时间时间戳毫秒privateRunnablerunnable;// 任务执行逻辑publicScheduleJob(intjobId,longtriggerTime,Runnablerunnable){this.jobIdjobId;this.triggerTimetriggerTime;this.runnablerunnable;}}// 初始化 publicXxlJobTimeWheel(){// 初始化时间槽每个槽位创建一个空的任务链表for(inti0;iWHEEL_SIZE;i){timeWheelSlots.add(newLinkedList());}// 启动时间轮每秒转动一格触发TICK_MS1000msscheduledExecutorService.scheduleAtFixedRate(this::tick,0,TICK_MS,TimeUnit.MILLISECONDS);}// 时间轮核心方法 /** * 时间轮转动一格核心移动指针 执行当前槽位的任务 */privatevoidtick(){// 1. 获取当前槽位指针位置intcurrentSlotcurrentPos.getAndIncrement()%WHEEL_SIZE;// 2. 获取当前时间戳longnowSystem.currentTimeMillis();// 3. 取出当前槽位的所有任务LinkedListScheduleJobslotJobstimeWheelSlots.get(currentSlot);if(slotJobs.isEmpty()){return;}// 4. 遍历执行任务迭代器防止并发修改IteratorScheduleJobiteratorslotJobs.iterator();while(iterator.hasNext()){ScheduleJobjobiterator.next();// 4.1 任务未到触发时间 → 放回可能是分层降级的任务if(job.triggerTimenow){continue;}// 4.2 执行任务异步执行避免阻塞时间轮CompletableFuture.runAsync(job.runnable);// 4.3 移除已执行的任务iterator.remove();}}/** * 添加任务到时间轮 * param job 待调度任务 */publicvoidaddJob(ScheduleJobjob){longnowSystem.currentTimeMillis();// 1. 任务已过期 → 直接执行if(job.triggerTimenow){CompletableFuture.runAsync(job.runnable);return;}// 2. 计算任务应放入的槽位longdelayjob.triggerTime-now;// 2.1 任务在当前轮盘范围内60秒内→ 放入对应槽位if(delayWHEEL_RANGE){// 计算槽位(当前指针 延迟时间/槽位大小) % 轮盘大小intslotPos(currentPos.get()(int)(delay/TICK_MS))%WHEEL_SIZE;timeWheelSlots.get(slotPos).add(job);}else{// 2.2 任务超过当前轮盘范围 → 分层降级简化版直接放入最后一个槽位实际XXL-Job会有分钟级轮盘// 注源码中会有多层时间轮秒→分→时此处简化intslotPos(currentPos.get()WHEEL_SIZE-1)%WHEEL_SIZE;timeWheelSlots.get(slotPos).add(job);}}/** * 关闭时间轮 */publicvoidshutdown(){scheduledExecutorService.shutdown();}// 测试示例 publicstaticvoidmain(String[]args)throwsInterruptedException{XxlJobTimeWheeltimeWheelnewXxlJobTimeWheel();// 添加测试任务13秒后执行timeWheel.addJob(newScheduleJob(1,System.currentTimeMillis()3000,()-{System.out.println(任务1执行System.currentTimeMillis());}));// 添加测试任务210秒后执行timeWheel.addJob(newScheduleJob(2,System.currentTimeMillis()10000,()-{System.out.println(任务2执行System.currentTimeMillis());}));// 阻塞主线程观察任务执行Thread.sleep(20000);timeWheel.shutdown();}}三、核心代码解释1. 时间轮初始化初始化WHEEL_SIZE60个槽位每个槽位对应1秒覆盖60秒范围启动一个单线程的定时任务每秒触发一次tick()方法时间轮转动一格。2. 核心方法tick()移动指针currentPos原子自增取模WHEEL_SIZE实现指针循环执行任务遍历当前槽位的任务链表执行已到触发时间的任务未到时间的任务保留等待下一轮异步执行任务通过CompletableFuture异步执行避免阻塞时间轮转动。3. 任务添加addJob()过期任务直接异步执行短期任务60秒内计算对应槽位放入链表长期任务超过60秒简化版放入最后一个槽位源码中会降级到「分钟级时间轮」到点后再放入秒级轮盘。四、XXLJOB 时间轮的设计亮点轻量级仅1个线程驱动资源消耗极低高并发任务链表采用LinkedList添加/删除效率高容错性任务执行失败不会阻塞时间轮XXL-Job 源码中还会增加重试逻辑分层设计通过「秒→分→时」分层支持长周期任务如几小时后执行。五、总结1. 核心原理时间轮通过「槽位指针任务链表」的结构将分散的定时任务批量管理核心是空间换时间用固定的槽位数量支撑海量任务的高效调度。2. 关键代码要点时间槽数组timeWheelSlots存储任务tick()方法驱动指针转动并执行任务addJob()计算任务槽位实现任务精准投放。3. 与XXL-Job源码的差异源码中时间轮会结合「线程池失败重试任务持久化」源码支持「分层时间轮」秒/分/时本示例简化为单层源码中任务触发后会通过「netty线程池」异步执行保证调度稳定性。