RxJava超时

时间:2017-10-05 08:13:56

标签: java timeout rx-java reactive-programming

我是RxJava的新手,我需要以异步方式使用Observable功能。

我还需要使用超时:在我的例子中,我希望每个进程在1秒或更短的时间内结束。

以下是我现在所做的事情:

public static void hello(String name) throws IOException {
Observable<String> obs2 = Observable.just(name).timeout(1000, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io());
    obs2.subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
            if("CCCCC".equals(s)){
                try {
                    Thread.sleep(3200);
                } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } 
        System.out.println(s + " " + new Date() +" "+Thread.currentThread().getName());
        }
    });
}

public static void main(final String[] args) throws InterruptedException, IOException {     
    hello("AAAAA");
    hello("CCCCC");
    hello("BBBBBB");
    System.in.read();
}

结果:

AAAAA Thu Oct 05 09:43:46 CEST 2017 RxIoScheduler-2
BBBBBB Thu Oct 05 09:43:46 CEST 2017 RxIoScheduler-4
CCCCC Thu Oct 05 09:43:49 CEST 2017 RxIoScheduler-3

我实际上期望从名为“RxIoScheduler-3”的线程中获取TimeoutException,因为它已经睡了3秒钟。

我的代码和我在RxJava中的超时方法出了什么问题?

感谢您帮助我。

2 个答案:

答案 0 :(得分:5)

根据the docstimeout运营商将:

  

镜像源Observable,但如果特定时间段过去没有任何发出的项目,则发出错误通知

因此,如果发光事件发生延迟,则认为已经发生超时但是您已经在消费事件中延迟并且不会导致超时

如果您重新编写代码以在发射期间暂停,则会发生超时。例如:

public static void hello(String name) throws IOException {
    Observable<String> obs2 = Observable.fromCallable(() -> {
                if ("CCCCC".equals(name)) {
                    // pause for 150ms before emitting "CCCCC"
                    try {
                        Thread.sleep(150);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return name;
            }
    ).timeout(100, MILLISECONDS) // timeout if there is a pause in emission of more than 100ms
            .subscribeOn(Schedulers.io());

    obs2.subscribe(s -> System.out.println(s + " " + new Date() + " " + Thread.currentThread().getName()),
            throwable -> System.err.println(throwable.getClass().getSimpleName() + " " + new Date() + " " + Thread.currentThread().getName()));
}

使用上面的hello()形式,您将获得写入控制台的以下输出:

AAAAA Thu Oct 05 10:10:33 IST 2017 RxIoScheduler-2
BBBBBB Thu Oct 05 10:10:33 IST 2017 RxIoScheduler-4
TimeoutException Thu Oct 05 10:10:33 IST 2017 RxComputationScheduler-1

答案 1 :(得分:0)

如果您无法控制正在使用的方法(例如使用库时),则可以使用Observable.timer运算符。您可以在执行操作(库调用)之前创建它。

long timeoutInSeconds = 5;
Disposable ssaiTimeout = Completable.timer(
                timeoutInSeconds,
                TimeUnit.SECONDS,
                AndroidSchedulers.mainThread())
                .subscribe(() -> {
                    // timeout occurred
                    // in case you do not have this method you can use a boolean flag
                    // to see if timeout occured and check agains that in getData
                    libraryClass.cancelRequest();
                    // handle timeout ...
                });

libraryClass.someAsynchronousRequest(new CallbackClass() {
    @Override
    public void getData(Data data) {
        ssaiTimeout.dispose();
        // do your stuff ...
    }
}