use of io.reactivex.rxjava3.subscribers.SerializedSubscriber in project RxJava by ReactiveX.
the class SerializedSubscriberTest method runConcurrencyTest.
@Test
public void runConcurrencyTest() {
ExecutorService tp = Executors.newFixedThreadPool(20);
try {
TestConcurrencySubscriber tw = new TestConcurrencySubscriber();
// we need Synchronized + SafeSubscriber to handle synchronization plus life-cycle
Subscriber<String> w = serializedSubscriber(new SafeSubscriber<>(tw));
w.onSubscribe(new BooleanSubscription());
Future<?> f1 = tp.submit(new OnNextThread(w, 12000));
Future<?> f2 = tp.submit(new OnNextThread(w, 5000));
Future<?> f3 = tp.submit(new OnNextThread(w, 75000));
Future<?> f4 = tp.submit(new OnNextThread(w, 13500));
Future<?> f5 = tp.submit(new OnNextThread(w, 22000));
Future<?> f6 = tp.submit(new OnNextThread(w, 15000));
Future<?> f7 = tp.submit(new OnNextThread(w, 7500));
Future<?> f8 = tp.submit(new OnNextThread(w, 23500));
// 12000 + 5000 + 75000 + 13500 + 22000 + 15000 + 7500 + 23500 = 173500
Future<?> f10 = tp.submit(new CompletionThread(w, TestConcurrencySubscriberEvent.onComplete, f1, f2, f3, f4, f5, f6, f7, f8));
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// ignore
}
waitOnThreads(f1, f2, f3, f4, f5, f6, f7, f8, f10);
// no check of type since we don't want to test barging results here, just interleaving behavior
int numNextEvents = tw.assertEvents(null);
assertEquals(173500, numNextEvents);
// System.out.println("Number of events executed: " + numNextEvents);
} catch (Throwable e) {
fail("Concurrency test failed: " + e.getMessage());
e.printStackTrace();
} finally {
tp.shutdown();
try {
tp.awaitTermination(25000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
use of io.reactivex.rxjava3.subscribers.SerializedSubscriber in project RxJava by ReactiveX.
the class SerializedSubscriberTest method threadStarvation.
/**
* Demonstrates thread starvation problem.
*
* No solution on this for now. Trade-off in this direction as per https://github.com/ReactiveX/RxJava/issues/998#issuecomment-38959474
* Probably need backpressure for this to work
*
* When using SynchronizedSubscriber we get this output:
*
* {@code p1: 18 p2: 68 =>} should be close to each other unless we have thread starvation
*
* When using SerializedSubscriber we get:
*
* {@code p1: 1 p2: 2445261 =>} should be close to each other unless we have thread starvation
*
* This demonstrates how SynchronizedSubscriber balances back and forth better, and blocks emission.
* The real issue in this example is the async buffer-bloat, so we need backpressure.
*
* @throws InterruptedException if the await is interrupted
*/
@Ignore("Demonstrates thread starvation problem. Read JavaDoc")
@Test
public void threadStarvation() throws InterruptedException {
TestSubscriber<String> ts = new TestSubscriber<>(new DefaultSubscriber<String>() {
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String t) {
// force it to take time when delivering
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
});
final Subscriber<String> subscriber = serializedSubscriber(ts);
AtomicInteger p1 = new AtomicInteger();
AtomicInteger p2 = new AtomicInteger();
subscriber.onSubscribe(new BooleanSubscription());
ResourceSubscriber<String> as1 = new ResourceSubscriber<String>() {
@Override
public void onNext(String t) {
subscriber.onNext(t);
}
@Override
public void onError(Throwable t) {
RxJavaPlugins.onError(t);
}
@Override
public void onComplete() {
}
};
ResourceSubscriber<String> as2 = new ResourceSubscriber<String>() {
@Override
public void onNext(String t) {
subscriber.onNext(t);
}
@Override
public void onError(Throwable t) {
RxJavaPlugins.onError(t);
}
@Override
public void onComplete() {
}
};
infinite(p1).subscribe(as1);
infinite(p2).subscribe(as2);
Thread.sleep(100);
System.out.println("p1: " + p1.get() + " p2: " + p2.get() + " => should be close to each other unless we have thread starvation");
// fairly distributed within 10000 of each other
assertEquals(p1.get(), p2.get(), 10000);
as1.dispose();
as2.dispose();
}
use of io.reactivex.rxjava3.subscribers.SerializedSubscriber in project RxJava by ReactiveX.
the class SerializedSubscriberTest method completeReentry.
@Test
public void completeReentry() {
final AtomicReference<Subscriber<Integer>> serial = new AtomicReference<>();
TestSubscriber<Integer> ts = new TestSubscriber<Integer>() {
@Override
public void onNext(Integer v) {
serial.get().onComplete();
serial.get().onComplete();
super.onNext(v);
}
};
SerializedSubscriber<Integer> sobs = new SerializedSubscriber<>(ts);
sobs.onSubscribe(new BooleanSubscription());
serial.set(sobs);
sobs.onNext(1);
ts.assertValue(1);
ts.assertComplete();
ts.assertNoErrors();
}
use of io.reactivex.rxjava3.subscribers.SerializedSubscriber in project RxJava by ReactiveX.
the class FlowableBufferTimed method subscribeActual.
@Override
protected void subscribeActual(Subscriber<? super U> s) {
if (timespan == timeskip && maxSize == Integer.MAX_VALUE) {
source.subscribe(new BufferExactUnboundedSubscriber<>(new SerializedSubscriber<>(s), bufferSupplier, timespan, unit, scheduler));
return;
}
Scheduler.Worker w = scheduler.createWorker();
if (timespan == timeskip) {
source.subscribe(new BufferExactBoundedSubscriber<>(new SerializedSubscriber<>(s), bufferSupplier, timespan, unit, maxSize, restartTimerOnMaxSize, w));
return;
}
// Can't use maxSize because what to do if a buffer is full but its
// timespan hasn't been elapsed?
source.subscribe(new BufferSkipBoundedSubscriber<>(new SerializedSubscriber<>(s), bufferSupplier, timespan, timeskip, unit, w));
}
use of io.reactivex.rxjava3.subscribers.SerializedSubscriber in project RxJava by ReactiveX.
the class FlowableDelay method subscribeActual.
@Override
protected void subscribeActual(Subscriber<? super T> t) {
Subscriber<? super T> downstream;
if (delayError) {
downstream = t;
} else {
downstream = new SerializedSubscriber<>(t);
}
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new DelaySubscriber<>(downstream, delay, unit, w, delayError));
}
Aggregations