RxJava调度程序 - 线程行为和饥饿?

时间:2015-09-11 04:09:08

标签: java multithreading reactive-programming rx-java

我与observeOn()subscribeOn()使用RxJava进行双重拍摄。我知道他们没有在单个流上并行排放。换句话说,单一的排放流只能放在一个线程上吗?我的测试似乎表明了这一点。我的理解是,您必须flatMap()调度程序(如.flatMap(v -> Observable.just(v).subscribeOn(Schedulers.computation()))中所述)在单个流上并行化排放。

如果是这种情况,那么调度程序会发生线程饥饿吗?如果我的计算调度程序有5个线程,但我有超过5个长时间运行的异步流正在处理,是否有可能发生饥饿?或者仅仅因为RxJava的性质,这不太可能吗?

public class Test {
    public static void main(String[] args) {


        Observable<String> airports = Observable.just("ABQ", "HOU", 
            "PHX", "DAL", "DFW", "AUS","SAN","LAX","JFK");


        airports.subscribeOn(Schedulers.io()).map(Test::stall)
        .subscribe(s -> System.out.println("Sub1 " + s +
                " " + Thread.currentThread().getName()));

        airports.subscribeOn(Schedulers.io()).map(Test::stall)
        .subscribe(s -> System.out.println("Sub2 " + s +
                " " + Thread.currentThread().getName()));

        sleep();
    }

    private static String stall(String str) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return str;
    }

    private static void sleep() {
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

1 个答案:

答案 0 :(得分:2)

使用flatMap,一个异步源可能会被其他人淹没,并且无法在自己的源上取得进展。然而,在实践中,我还没有看到这种情况发生,因为操作系统和JVM打嗝提供了足够的喘息空间以及flatMap本身的背压和仲裁。如果您担心这种压倒性的问题,可以将maxConcurrent参数与flatMap重载一起使用,并限制并发订阅的数量。

RxJava主要以非阻塞方式编写,因此当需要合并或组合源时,它们并不真正等待彼此。

计算调度程序是一个单线程执行程序池,以循环方式分配给调用者。我不了解标准执行者的公平性。