Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.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
Java9反应流:一个订阅者是否属于一个发布者_Java_Reactive Programming_Java 9_Reactive - Fatal编程技术网

Java9反应流:一个订阅者是否属于一个发布者

Java9反应流:一个订阅者是否属于一个发布者,java,reactive-programming,java-9,reactive,Java,Reactive Programming,Java 9,Reactive,我想知道,如果发布服务器正在停止运行(例如被关闭),被动流发布服务器是否可以安全地假定订阅只属于它,java.util.concurrent.Flow.Subscriber#onComplete。下面的代码示例演示了这一困境(显然,这只是一些演示问题的合成代码): import java.util.concurrent.ConcurrentLinkedQueue; 导入java.util.concurrent.Flow; 导入java.util.concurrent.ScheduledExecu

我想知道,如果发布服务器正在停止运行(例如被关闭),被动流发布服务器是否可以安全地假定订阅只属于它
java.util.concurrent.Flow.Subscriber#onComplete
。下面的代码示例演示了这一困境(显然,这只是一些演示问题的合成代码):

import java.util.concurrent.ConcurrentLinkedQueue;
导入java.util.concurrent.Flow;
导入java.util.concurrent.ScheduledExecutorService;
导入java.util.concurrent.ScheduledThreadPoolExecutor;
导入java.util.concurrent.TimeUnit;
公共类TimePublisher实现Flow.Publisher{
私有最终ScheduledExecutorService ScheduledExecutorService=新ScheduledThreadPoolExecutor(1);

private final ConcurrentLinkedQueue订户的文档说

此接口中的方法按每个流的严格顺序调用。订阅

onComplete
特别是:

方法,当已知未因错误而终止的订阅不会发生其他订阅方方法调用时调用。在此之后,订阅不会调用任何其他订阅方方法。如果此方法引发异常,则结果行为未定义

因此,其他订阅继续调用方法是合法的

Flow
文档说明在一个
订阅者中有多个
订阅
s是可能的,但不建议:

由于对给定Flow.Subscription的订户方法调用是严格排序的,因此这些方法不需要使用锁或volatile,除非订户维护多个订阅(在这种情况下,最好定义多个订户,每个订户都有自己的订阅)

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Flow;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TimePublisher implements Flow.Publisher<Long> {

    private final ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);

    private final ConcurrentLinkedQueue<Flow.Subscriber<? super Long>> subscribersList = new ConcurrentLinkedQueue<>();


    private TimePublisher() {

    }

    public static TimePublisher newInstance() {
        TimePublisher timePublisher = new TimePublisher();
        timePublisher.startTickScheduler();

        return timePublisher;
    }

    private void startTickScheduler() {
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            // does not make too much sense: just for the sake of the example
            final long currentTimeMillis = System.currentTimeMillis();
            subscribersList.forEach(sub -> sub.onNext(currentTimeMillis));
        }, 1, 1, TimeUnit.SECONDS);
    }

    @Override
    public void subscribe(Flow.Subscriber<? super Long> subscriber) {

        subscribersList.add(subscriber);

        subscriber.onSubscribe(new Flow.Subscription() {
            @Override
            public void request(long n) {
                // no-op in this sample
            }

            @Override
            public void cancel() {
                subscribersList.remove(subscriber);
            }
        });
    }

    public void stop() {
        // the publisher can be stopped from the outside: after that it will
        // definitely not emit any next items.
        scheduledExecutorService.shutdown();

        // QUESTION: can we assume that a Subscriber is subscribed to only this Publisher?
        // if it is subscribed to another publisher, the following is illegal, as onNext
        // could potentially be called by another Publisher...
        subscribersList.forEach(Flow.Subscriber::onComplete);

        subscribersList.clear();
    }
}