/** * Can receive timeout if subscribe never receives an onError/onCompleted ... which reveals a race * condition. */ @Test(timeout = 10000) public void testSubscribeCompletionRaceCondition() { for (int i = 0; i < 50; i++) { final ReplaySubject<String> subject = ReplaySubject.create(); final AtomicReference<String> value1 = new AtomicReference<String>(); subject.subscribe( new Action1<String>() { @Override public void call(String t1) { try { // simulate a slow observer Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } value1.set(t1); } }); Thread t1 = new Thread( new Runnable() { @Override public void run() { subject.onNext("value"); subject.onCompleted(); } }); SubjectObserverThread t2 = new SubjectObserverThread(subject); SubjectObserverThread t3 = new SubjectObserverThread(subject); SubjectObserverThread t4 = new SubjectObserverThread(subject); SubjectObserverThread t5 = new SubjectObserverThread(subject); t2.start(); t3.start(); t1.start(); t4.start(); t5.start(); try { t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } assertEquals("value", value1.get()); assertEquals("value", t2.value.get()); assertEquals("value", t3.value.get()); assertEquals("value", t4.value.get()); assertEquals("value", t5.value.get()); } }