顾名思义,节流阀的作用是限制某些事件的执行频率,基本代码如下:
obj.event = function(){ clearTimeout(obj.timer); obj.timer = setTimeout(() => { execute }, timeout);}
在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来记住任务的执行情况
// 应该只会输出一个2List<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 2List<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
作者:0xcaffebabe
链接:https://www.imooc.com/article/305039
转自来源:慕课网
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。