Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rx java 接收运营商的执行顺序_Rx Java - Fatal编程技术网

Rx java 接收运营商的执行顺序

Rx java 接收运营商的执行顺序,rx-java,Rx Java,我试图弄清楚Rx操作员的执行顺序 我所知道的是,最后一个是create操作符,也就是说,在订户出现之前,可观察对象不会创建(冷可观察) 因此,我编写了以下代码来测试这种行为: public static void main(String[] args) throws InterruptedException { test(Schedulers.immediate()); test(Schedulers.computation()); ExecutorService ex

我试图弄清楚Rx操作员的执行顺序

我所知道的是,最后一个是create操作符,也就是说,在订户出现之前,可观察对象不会创建(冷可观察)

因此,我编写了以下代码来测试这种行为:

public static void main(String[] args) throws InterruptedException {

    test(Schedulers.immediate());
    test(Schedulers.computation());
    ExecutorService executor = Executors.newCachedThreadPool();
    test(Schedulers.from(executor));
    executor.shutdown();
    test(Schedulers.io());
    test(Schedulers.newThread());
    test(Schedulers.trampoline());

}


static void test(Scheduler scheduler) throws InterruptedException {
    System.out.printf("-------%s--------\n", scheduler);

    Observable<Integer> create = Observable.create(c -> {
        c.onNext(1);
        c.onCompleted();
        print("CREATE");
    });

    create
    .subscribeOn(scheduler)
    .observeOn(scheduler) .map(e -> { print("MAP"); return e * 2; })
    .observeOn(scheduler) .subscribe(a -> { print("SUBSCRIBE");});

    TimeUnit.MILLISECONDS.sleep(200);
}

static synchronized void print(String s) {
    System.out.printf("%s %s\n", s, Thread.currentThread());
}
它同时显示
立即调度程序
蹦床调度程序(都在主线程上运行),以我期望的正确方式执行

但是其他调度器是不同的(但是我正在同步
方法
print
,这意味着我正在防止
std输出发生争用情况)


那么,为什么会发生这种情况呢?

immediate
trampoline
调度程序使用当前(单个)线程,因此严格定义了执行顺序

所有其他调度程序都是多线程的。您可以将三个任务调度到三个不同的线程

MAP应始终位于SUBSCRIBE之前,因为SUBSCRIBE仅在MAP完成后调度(MAP()的结果传递给subscriber)


除此之外,绝对不能保证任务按什么顺序序列化(通过
打印
函数)。

因为您的可观察对象是冷链,所以在调用subscribe之前不会启动

当您调用subscribe-chain时,启动并首先调用
rx.Observable.OnSubscribe#call
,然后当您调用
rx.observator#onNext
时,将值提交给chain。因为您指定了调度程序,调用发布到另一个线程的
map
,而主线程有时间(或没有时间)完成
rx.Observable.OnSubscribe#call

如果将
print(“CREATE”)
移动到
rx.Observer\onNext
上方,则序列将始终为CREATE->MAP->SUBSCRIBE

在这种情况下,始终在订阅之前映射。如果所有内容都在一个线程中运行,则CREATE是最后一个线程,其他线程处于未定义位置。由于线程切换,位置未定义

根据评论更新

为什么在映射线程之前创建订阅线程

每个操作符将可观察的对象包装成另一个并返回它们

调用
subscribe()
调用
rx.Observable.OnSubscribe时#调用上次创建的Observable

然后处理通过堆栈执行的操作

rx.internal.operators.OnSubscribeMap#call
rx.internal.operators.OperatorObserveOn#call
rx.internal.operators.OnSubscribeMap#call
rx.internal.operators.OperatorSubscribeOn#call
...
如果您查看
操作员观察
(代码剪切)

公共最终类运算符observeOn实现运算符{
公共运算符ObserveOn(调度程序、布尔延迟错误、int-bufferSize){
this.scheduler=调度程序;
this.delayError=delayError;
this.bufferSize=(bufferSize>0)?bufferSize:RxRingBuffer.SIZE;
}
@凌驾

publicsubscriberTanks;我刚刚注意到按照以下顺序创建的线程:(subscribe,map,create)-基于线程编号。但是否应该像主线程案例中那样映射susbscibe create?@MuhammadHewedy创建线程的顺序并不重要。无论如何,无法保证特定的顺序。这是多线程的本质。您是否收到相同的结果(所有调度程序的顺序相同)每次运行程序时?请尝试并检查5-10次。无论创建与否;那么为什么要在上面的映射线程之前创建订阅线程?在案例2、3、4、5(除了第一个和最后一个)中,我没有看到任何情况下订阅在映射线程之前,SUBSCRIBE的线程编号在MAP的线程编号之前;
MAP的线程编号之前;
MAP的线程编号之前执行(实际的线程运行顺序不是我要说的)首先被误解了。这是因为observeOn的堆栈(后进先出)请参阅rx.internal.operators.OperatorObserveOn#call我认为很难在注释中解释。每次调用observeOn时,它都会创建新的observeable,当您调用subscribe流程时,我认为代码更好。从observeOn开始,深入了解
rx.internal.operators.OnSubscribeMap#call
rx.internal.operators.OperatorObserveOn#call
rx.internal.operators.OnSubscribeMap#call
rx.internal.operators.OperatorSubscribeOn#call
...
public final class OperatorObserveOn<T> implements Operator<T, T> {

    public OperatorObserveOn(Scheduler scheduler, boolean delayError, int bufferSize) {
        this.scheduler = scheduler;
        this.delayError = delayError;
        this.bufferSize = (bufferSize > 0) ? bufferSize : RxRingBuffer.SIZE;
    }

    @Override
    public Subscriber<? super T> call(Subscriber<? super T> child) {
        if (scheduler instanceof ImmediateScheduler) {
            // avoid overhead, execute directly
            return child;
        } else if (scheduler instanceof TrampolineScheduler) {
            // avoid overhead, execute directly
            return child;
        } else {
            ObserveOnSubscriber<T> parent = new ObserveOnSubscriber<T>(scheduler, child, delayError, bufferSize);
            parent.init();
            return parent;
        }
    }

    /** Observe through individual queue per observer. */
    static final class ObserveOnSubscriber<T> extends Subscriber<T> implements Action0 {
        public ObserveOnSubscriber(Scheduler scheduler, Subscriber<? super T> child, boolean delayError, int bufferSize) {
            this.child = child;
            this.recursiveScheduler = scheduler.createWorker();
            this.delayError = delayError;
            this.on = NotificationLite.instance();
            int calculatedSize = (bufferSize > 0) ? bufferSize : RxRingBuffer.SIZE;
            // this formula calculates the 75% of the bufferSize, rounded up to the next integer
            this.limit = calculatedSize - (calculatedSize >> 2);
            if (UnsafeAccess.isUnsafeAvailable()) {
                queue = new SpscArrayQueue<Object>(calculatedSize);
            } else {
                queue = new SpscAtomicArrayQueue<Object>(calculatedSize);
            }
            // signal that this is an async operator capable of receiving this many
            request(calculatedSize);
        }
    }
}