最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot時(shí)間輪實(shí)現(xiàn)延時(shí)任務(wù)的示例代碼

 更新時(shí)間:2025年10月30日 08:20:09   作者:風(fēng)象南  
在日常開發(fā)中,我們經(jīng)常需要處理各種定時(shí)任務(wù):用戶注冊(cè)后的歡迎郵件、訂單超時(shí)自動(dòng)取消、緩存定期刷新等,傳統(tǒng)的定時(shí)器方案在面對(duì)大規(guī)模定時(shí)任務(wù)時(shí)往往力不從心,所以本文給大家介紹了SpringBoot時(shí)間輪實(shí)現(xiàn)延時(shí)任務(wù),需要的朋友可以參考下

傳統(tǒng)方案的困境

在日常開發(fā)中,我們經(jīng)常需要處理各種定時(shí)任務(wù):用戶注冊(cè)后的歡迎郵件、訂單超時(shí)自動(dòng)取消、緩存定期刷新等。傳統(tǒng)的定時(shí)器方案在面對(duì)大規(guī)模定時(shí)任務(wù)時(shí)往往力不從心:

性能瓶頸日益凸顯

  • ScheduledExecutor在處理上千個(gè)任務(wù)時(shí)性能急劇下降
  • Timer類不僅線程不安全,還存在單點(diǎn)故障風(fēng)險(xiǎn)
  • 每次調(diào)度都要在堆中查找最小元素,時(shí)間復(fù)雜度O(log n)
  • 頻繁的GC壓力導(dǎo)致系統(tǒng)吞吐量受限

業(yè)務(wù)需求日益復(fù)雜

  • 消息重試需要指數(shù)退避策略
  • 分布式系統(tǒng)需要精確的延遲調(diào)度
  • 會(huì)話管理需要?jiǎng)討B(tài)添加刪除任務(wù)
  • 限流器需要高效的時(shí)間窗口控制

時(shí)間輪的誕生

時(shí)間輪(Timing Wheel) 靈感來源于我們?nèi)粘J褂玫臅r(shí)鐘。想象一下老式機(jī)械表的工作原理

  • 表盤被分成12個(gè)小時(shí)刻度,時(shí)針每12小時(shí)轉(zhuǎn)一圈
  • 分針每分鐘移動(dòng)一格,60分鐘轉(zhuǎn)一圈
  • 秒針每秒移動(dòng)一格,60秒轉(zhuǎn)一圈

時(shí)間輪借鑒了這個(gè)思想,將時(shí)間劃分成固定的槽位,通過指針的移動(dòng)來調(diào)度任務(wù)。這種巧妙的設(shè)計(jì)將時(shí)間維度空間化,用簡(jiǎn)單的指針移動(dòng)代替了復(fù)雜的堆操作。

核心設(shè)計(jì)哲學(xué)

時(shí)間離散化:將連續(xù)時(shí)間分割成等長(zhǎng)的tick間隔

空間映射:每個(gè)時(shí)間間隔對(duì)應(yīng)一個(gè)槽位

批量觸發(fā):同一槽位的任務(wù)一起執(zhí)行

輪次計(jì)數(shù):多圈任務(wù)通過輪數(shù)計(jì)算

為什么時(shí)間輪如此高效?

時(shí)間輪的巧妙之處在于它徹底改變了任務(wù)調(diào)度的思路:

時(shí)間復(fù)雜度的革命 從O(log n)到O(1)

  • 傳統(tǒng)方案:需要在堆中查找最小元素
  • 時(shí)間輪:直接計(jì)算目標(biāo)槽位,一次到位

內(nèi)存訪問的優(yōu)化

  • 順序訪問數(shù)組元素,CPU緩存命中率高
  • 相比堆結(jié)構(gòu)的隨機(jī)訪問,性能提升明顯

批量處理的威力

  • 同一槽位的多個(gè)任務(wù)批量觸發(fā)
  • 減少線程切換和調(diào)度開銷
  • 提高系統(tǒng)的整體吞吐量

算法設(shè)計(jì):從時(shí)鐘模型到數(shù)據(jù)結(jié)構(gòu)

時(shí)間輪的工作原理

想象一個(gè)真實(shí)的時(shí)鐘

  • 時(shí)鐘有12個(gè)小時(shí)刻度,每個(gè)刻度代表一個(gè)小時(shí)
  • 秒針每秒移動(dòng)一格,分針每分鐘移動(dòng)一格,時(shí)針每小時(shí)移動(dòng)一格
  • 我們可以通過指針的位置確定當(dāng)前時(shí)間

時(shí)間輪采用了類似的概念

  • 將時(shí)間劃分為N個(gè)槽位(通常是2的冪次,如512個(gè))
  • 每個(gè)槽位代表一個(gè)固定的時(shí)間間隔(如100ms)
  • 一個(gè)指針周期性地移動(dòng)到下一個(gè)槽位
  • 當(dāng)指針到達(dá)某個(gè)槽位時(shí),執(zhí)行該槽位中的所有任務(wù)

核心數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)

時(shí)間輪主體結(jié)構(gòu)

時(shí)間輪數(shù)組:
[Slot0][Slot1][Slot2]...[Slot511]
  ↑       ↑       ↑         ↑
 指針    100ms后   200ms后    51.1秒后

槽位(Slot)設(shè)計(jì)

  • 使用ConcurrentLinkedQueue存儲(chǔ)任務(wù)列表,保證線程安全
  • 維護(hù)任務(wù)計(jì)數(shù)器,便于快速統(tǒng)計(jì)
  • 記錄最后訪問時(shí)間,用于監(jiān)控和清理

任務(wù)包裝器(TimerTaskWrapper)

  • 包裝原始任務(wù)和相關(guān)信息
  • 記錄任務(wù)的到期時(shí)間和需要經(jīng)過的輪數(shù)
  • 維護(hù)任務(wù)狀態(tài)(等待、運(yùn)行、完成、失敗、取消)
  • 提供任務(wù)進(jìn)度和剩余時(shí)間計(jì)算

算法關(guān)鍵步驟

任務(wù)調(diào)度算法

  1. 計(jì)算任務(wù)需要經(jīng)過的tick數(shù)量:ticks = delayMs / tickDuration
  2. 計(jì)算目標(biāo)槽位:targetSlot = (currentSlot + ticks) % slotSize
  3. 計(jì)算需要經(jīng)過的輪數(shù):rounds = ticks / slotSize
  4. 將任務(wù)包裝后放入目標(biāo)槽位

指針移動(dòng)算法

  1. 周期性地將指針移動(dòng)到下一個(gè)槽位
  2. 處理當(dāng)前槽位中的所有任務(wù)
  3. 對(duì)于未到期的任務(wù),輪數(shù)減1后重新入槽
  4. 對(duì)于到期的任務(wù),提交到工作線程池執(zhí)行

多輪任務(wù)處理

  • 當(dāng)任務(wù)延遲時(shí)間超過一圈時(shí),需要記錄剩余輪數(shù)
  • 每次指針經(jīng)過時(shí),如果輪數(shù)>0,則輪數(shù)減1
  • 只有輪數(shù)為0的任務(wù)才會(huì)被執(zhí)行

核心實(shí)現(xiàn):高性能調(diào)度引擎

線程模型設(shè)計(jì)

雙線程池架構(gòu)是時(shí)間輪高性能的關(guān)鍵

調(diào)度線程池(單線程):
    ↓
周期性移動(dòng)指針
    ↓
處理槽位任務(wù)
    ↓
提交到工作線程池

工作線程池(多線程):
    ↓
并發(fā)執(zhí)行任務(wù)
    ↓
處理業(yè)務(wù)邏輯
    ↓
更新任務(wù)狀態(tài)

調(diào)度線程池

  • 使用單線程避免并發(fā)問題
  • 負(fù)責(zé)指針移動(dòng)和槽位處理
  • 通過scheduleAtFixedRate實(shí)現(xiàn)周期性調(diào)度
  • 設(shè)置為守護(hù)線程,不阻止JVM退出

SpringBoot的完整實(shí)現(xiàn)

服務(wù)層

TimingWheelService設(shè)計(jì)

@Service
public class TimingWheelService {
    // 任務(wù)管理
    public String scheduleTask(TimerTask task, long delayMs);
    public boolean cancelTask(String taskId);
    public List<TimerTaskWrapper> getActiveTasks();

    // 統(tǒng)計(jì)信息
    public TimingWheelStats getStats();
    public TaskExecutionStats getExecutionStats();

    // 任務(wù)清理
    public int cleanupCompletedTasks();

    // 示例任務(wù)
    public String createSampleTask(String type, long delayMs);
    public List<String> createBatchTasks(int count, long minDelay, long maxDelay);
}

核心配置類

/**
 * 時(shí)間輪配置類
 */
@Configuration
@EnableConfigurationProperties(TimingWheelProperties.class)
public class TimingWheelConfig {

    @Bean
    public TimingWheel timingWheel(TimingWheelProperties properties, MeterRegistry meterRegistry) {
        log.info("Creating timing wheel with properties: {}", properties);
        return new TimingWheel(properties, meterRegistry);
    }

    @Bean
    public MetricsConfig metricsConfig(MeterRegistry meterRegistry) {
        return new MetricsConfig(meterRegistry);
    }

    @Bean
    public WebConfig webConfig() {
        return new WebConfig();
    }
}

REST API接口

/**
 * 時(shí)間輪控制器
 */
@RestController
@RequestMapping("/api/timingwheel")
@CrossOrigin(origins = "*")
public class TimingWheelController {

    @Autowired
    private TimingWheelService timingWheelService;

    /**
     * 獲取時(shí)間輪統(tǒng)計(jì)信息
     */
    @GetMapping("/stats")
    public ResponseEntity<TimingWheel.TimingWheelStats> getStats() {
        TimingWheel.TimingWheelStats stats = timingWheelService.getStats();
        return ResponseEntity.ok(stats);
    }

    /**
     * 創(chuàng)建示例任務(wù)
     */
    @PostMapping("/tasks/sample")
    public ResponseEntity<Map<String, Object>> createSampleTask(@RequestBody Map<String, Object> request) {
        String type = (String) request.getOrDefault("type", "simple");
        long delay = ((Number) request.getOrDefault("delay", 1000)).longValue();

        String taskId = timingWheelService.createSampleTask(type, delay);

        Map<String, Object> response = new HashMap<>();
        response.put("taskId", taskId);
        response.put("type", type);
        response.put("delay", delay);
        response.put("message", "Task created successfully");

        return ResponseEntity.ok(response);
    }

    /**
     * 批量創(chuàng)建任務(wù)
     */
    @PostMapping("/tasks/batch")
    public ResponseEntity<Map<String, Object>> createBatchTasks(@RequestBody Map<String, Object> request) {
        int count = (Integer) request.getOrDefault("count", 10);
        long minDelay = ((Number) request.getOrDefault("minDelay", 1000)).longValue();
        long maxDelay = ((Number) request.getOrDefault("maxDelay", 10000)).longValue();

        List<String> taskIds = timingWheelService.createBatchTasks(count, minDelay, maxDelay);

        Map<String, Object> response = new HashMap<>();
        response.put("taskIds", taskIds);
        response.put("count", taskIds.size());
        response.put("message", "Batch tasks created successfully");

        return ResponseEntity.ok(response);
    }

    /**
     * 壓力測(cè)試
     */
    @PostMapping("/stress-test")
    public ResponseEntity<Map<String, Object>> stressTest(@RequestBody Map<String, Object> request) {
        int taskCount = (Integer) request.getOrDefault("taskCount", 1000);
        long minDelay = ((Number) request.getOrDefault("minDelay", 100)).longValue();
        long maxDelay = ((Number) request.getOrDefault("maxDelay", 5000)).longValue();

        long startTime = System.currentTimeMillis();
        List<String> taskIds = timingWheelService.createBatchTasks(taskCount, minDelay, maxDelay);
        long endTime = System.currentTimeMillis();

        Map<String, Object> response = new HashMap<>();
        response.put("taskCount", taskIds.size());
        response.put("creationTime", endTime - startTime);
        response.put("throughput", taskIds.size() * 1000.0 / (endTime - startTime));
        response.put("message", "Stress test completed successfully");

        return ResponseEntity.ok(response);
    }
}

應(yīng)用配置

# application.yml
server:
  port: 8081
  servlet:
    context-path: /

spring:
  application:
    name: springboot-timingwheel

# Timing Wheel Configuration
timingwheel:
  config:
    slot-size: 512
    tick-duration: 100
    worker-threads: 4
    enable-multi-wheel: true
    enable-metrics: true
    task-timeout: 30000

logging:
  level:
    com.example.timingwheel: DEBUG
    org.springframework.web: INFO
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

總結(jié)

本文展示了時(shí)間輪的設(shè)計(jì)與實(shí)現(xiàn),從算法原理到可視化監(jiān)控。時(shí)間輪通過巧妙的時(shí)間維度空間化思想,用簡(jiǎn)單的指針移動(dòng)實(shí)現(xiàn)了高效的定時(shí)任務(wù)調(diào)度,在高并發(fā)場(chǎng)景下展現(xiàn)出卓越的性能優(yōu)勢(shì)。

以上就是SpringBoot時(shí)間輪實(shí)現(xiàn)延時(shí)任務(wù)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot時(shí)間輪延時(shí)任務(wù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

和田市| 宁南县| 霸州市| 手游| 广河县| 阿克苏市| 安塞县| 乌兰县| 互助| 靖远县| 大理市| 浦城县| 南靖县| 台安县| 绥滨县| 庆城县| 安西县| 扶余县| 都匀市| 建宁县| 手游| 石景山区| 贡山| 嘉禾县| 龙陵县| 肇源县| 赤水市| 庆城县| 宁化县| 新泰市| 辉县市| 那曲县| 永靖县| 安陆市| 抚远县| 浦东新区| 鹰潭市| 府谷县| 道真| 洛隆县| 武陟县|