JAVA實現節流閥

lcc發表於2021-09-09

JAVA實現節流閥

在前端開發中,有種效果叫做節流閥

顧名思義,節流閥的作用是限制某些事件的執行頻率,基本程式碼如下:

obj.event = function(){
  clearTimeout(obj.timer);
  obj.timer = setTimeout(() => {
    execute
  }, timeout);
}

JAVA實現

在JAVA中,我們也需要一些類似的效果

抽象

我們抽象出一個pool,這個pool可以接受你的任務,如果是同一個任務,會覆蓋之前還沒執行的任務

class Pool {
    void execute(String key,Runnable runnable,long delay){}
}

這裡的key就代表你的任務,delay就是任務的間隔時間

使用執行緒池

我們可以引入執行緒池來簡化編碼

private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(6);

執行緒池的作用是進行任務排程,ScheduledExecutorService允許我們提交一個延遲執行的任務

思路

當程式設計師提交一個任務,pool會判斷這個任務是否在pool中待執行,
如果是待執行,則取消pool中的任務,後用新提交的這個任務替代它

scheduledExecutorService提交任務會返回一個future,在執行之前,我們可以取消它

完整程式碼如下

void execute(String key,Runnable runnable,long delay){
    ScheduledFuture<?> task = map.get(key);
    if (task != null){
        task.cancel(false);
    }
    ScheduledFuture<?> schedule = scheduledExecutorService.schedule(()->{
        runnable.run();
        map.remove(key);
    }, delay, TimeUnit.MILLISECONDS);
    map.put(key,schedule);
}

這裡使用了一個map來記住任務的執行情況

測試

  • 第一個測試
// 應該只會輸出一個2
List<Integer> list = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(1);
Pool pool = new Pool();
for (int i = 0; i < 3; i++) {
    int finalI = i;
    pool.execute("task",()->{
        System.out.println(finalI);
        list.add(finalI);
        latch.countDown();
    },1000);
    Thread.sleep(800);
}
latch.await();
assertEquals(1,list.size());
assertEquals(2,list.get(0));

這裡依次執行三次任務,但是這個任務的延遲時間是1000,任務執行的間隔是800

間隔比延遲實現還要小,所以前面2個任務會被忽略,結果只會輸出2

  • 第二個測試
// 應該輸出 0 1 2
List<Integer> list = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(3);
Pool pool = new Pool();
for (int i = 0; i < 3; i++) {
    int finalI = i;
    pool.execute("task",()->{
        System.out.println(finalI);
        list.add(finalI);
        latch.countDown();
    },1000);
    Thread.sleep(1100);
}
latch.await();
assertEquals(3,list.size());
assertEquals(3,list.size());

這個測試任務間隔比延遲還要大,所以三個任務會被依次執行

輸出 0 1 2

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2331/viewspace-2825535/,如需轉載,請註明出處,否則將追究法律責任。

相關文章