前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RxJava 之 TestScheduler

RxJava 之 TestScheduler

作者头像
fengzhizi715
发布2018-08-24 17:20:37
8410
发布2018-08-24 17:20:37
举报

TestScheduler 是专门用于测试的调度器,跟其他调度器的区别是TestScheduler只有被调用了时间才会继续。TestScheduler是一种特殊的、非线程安全的调度器,用于测试一些不引入真实并发性、允许手动推进虚拟时间的调度器。

在 RxJava2.x 中,原先RxJava1.x的Schedulers.test()被去掉了,想要获得TestScheduler对象可以通过直接new TestScheduler()的方式来实现。

TestScheduler 所包含的方法并不多,下面罗列几个关键的方法。

advanceTimeTo

将调度器的时钟移动到某个特定时刻。

例如:

时钟移动到10毫秒。

代码语言:javascript
复制
scheduler.advanceTimeTo(10, TimeUnit.MILLISECONDS);

时钟移动到20毫秒。

代码语言:javascript
复制
scheduler.advanceTimeBy(20, TimeUnit.MILLISECONDS);

下面的列子展示了0秒、20秒、40秒会打印不同的结果。

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("immediate");
            }
        });

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("20s");
            }
        },20, TimeUnit.SECONDS);

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("40s");
            }
        },40, TimeUnit.SECONDS);

        scheduler.advanceTimeTo(1, TimeUnit.MILLISECONDS);
        System.out.println("virtual time: " + scheduler.now(TimeUnit.MILLISECONDS));

        scheduler.advanceTimeTo(20, TimeUnit.SECONDS);
        System.out.println("virtual time: " + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeTo(40, TimeUnit.SECONDS);
        System.out.println("virtual time: " + scheduler.now(TimeUnit.SECONDS));

执行结果:

代码语言:javascript
复制
immediate
virtual time: 1
20s
virtual time: 20
40s
virtual time: 40

我们可以看到使用advanceTimeTo之后,移动不同的时间点会打印不同的内容。

当然,advanceTimeTo()也可以传负数,表示回到过去的时间点。但是一般不推荐这种用法。

advanceTimeBy

将调度程序的时钟按指定的时间向前移动。

例如:

时钟移动了10毫秒。

代码语言:javascript
复制
scheduler.advanceTimeBy(10, TimeUnit.MILLISECONDS);

再次调用刚才的方法,时钟又会移动了10毫秒。此时,时钟移动也到20毫秒,这是一个累加的过程。

代码语言:javascript
复制
scheduler.advanceTimeBy(10, TimeUnit.MILLISECONDS);

下面的例子使用了timer操作符,timer是按照指定时间延迟发送的操作符,timer()并不会按周期地执行。该例子展示了2秒后atomicLong会自动加1

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        final AtomicLong atomicLong = new AtomicLong();
        Observable.timer(2, TimeUnit.SECONDS, scheduler).subscribe(new Consumer<Long>() {
            @Override
            public void accept(final Long value) throws Exception {
                atomicLong.incrementAndGet();
            }
        });

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(1, TimeUnit.SECONDS);

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(1, TimeUnit.SECONDS);

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

执行结果:

代码语言:javascript
复制
atomicLong's value=0, virtual time:0
atomicLong's value=0, virtual time:1
atomicLong's value=1, virtual time:2

这个结果符合预期,最初atomicLong为0,时钟移动到1秒它的值仍然为0,时钟再移动1秒相当于时钟移动到2秒,所以它的值变为1。

当然,advanceTimeBy()也可以传负数,表示回到过去。

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        final AtomicLong atomicLong = new AtomicLong();
        Observable.timer(2, TimeUnit.SECONDS, scheduler).subscribe(new Consumer<Long>() {
            @Override
            public void accept(final Long value) throws Exception {
                atomicLong.incrementAndGet();
            }
        });

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(1, TimeUnit.SECONDS);

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(-1, TimeUnit.SECONDS);

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(2, TimeUnit.SECONDS);

        System.out.println("atomicLong's value="+atomicLong.get() + ", virtual time:" + scheduler.now(TimeUnit.SECONDS));

执行结果:

代码语言:javascript
复制
atomicLong's value=0, virtual time:0
atomicLong's value=0, virtual time:1
atomicLong's value=0, virtual time:0
atomicLong's value=1, virtual time:2

triggerActions

triggerActions不会修改时间,它执行任何计划中的但是未启动的任务,已经执行过的任务不会再启动。

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("immediate");
            }
        });

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("20s");
            }
        },20, TimeUnit.SECONDS);

        System.out.println("virtual time: " + scheduler.now(TimeUnit.SECONDS));

执行结果:

代码语言:javascript
复制
virtual time: 0

稍微改一下代码,增加scheduler.triggerActions()

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("immediate");
            }
        });

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("20s");
            }
        },20, TimeUnit.SECONDS);

        scheduler.triggerActions();
        System.out.println("virtual time: " + scheduler.now(TimeUnit.SECONDS));

执行结果:

代码语言:javascript
复制
immediate
virtual time: 0

此时由于执行了triggerActions(),所以打印了immediate。

再改一下,增加advanceTimeBy()

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("immediate");
            }
        });

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("20s");
            }
        },20, TimeUnit.SECONDS);

        scheduler.triggerActions();
        System.out.println("virtual time: " + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(20,TimeUnit.SECONDS);

执行结果:

代码语言:javascript
复制
immediate
virtual time: 0
20s

如果将triggerActions()放在最后,看看效果

代码语言:javascript
复制
        TestScheduler scheduler = new TestScheduler();

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("immediate");
            }
        });

        scheduler.createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("20s");
            }
        },20, TimeUnit.SECONDS);


        System.out.println("virtual time: " + scheduler.now(TimeUnit.SECONDS));

        scheduler.advanceTimeBy(20,TimeUnit.SECONDS);
        scheduler.triggerActions();

执行结果:

代码语言:javascript
复制
virtual time: 0
immediate
20s

因为已经使用了advanceTimeBy(),所以即使再调用triggerActions()也不会执行已经启动过的任务。

总结

对于测试一些需要精确时间的任务,TestScheduler还是很有用处的,可以节省很多等待的时间。

参考资料:

  1. http://blog.chengyunfeng.com/?p=979
  2. https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.10.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • advanceTimeTo
  • advanceTimeBy
  • triggerActions
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档