简体   繁体   中英

Observable is not asynchronous

I am learning RxJava and am testing a scenario where I read data from a DB and then post it to a Queue. I just made a sample mock of the whole process but I don't seem to find the Observable working as I wanted it to ie. asynchronously.

This is my code:

package rxJava;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.Observer;
import rx.functions.Action1;

public class TestClass {

    public static void main(String[] args) {

        TestClass test = new TestClass();
        System.out.println("---START---");

        test.getFromDB().subscribe(new Observer<String>() {

            @Override
            public void onCompleted() {
                System.out.println("Publish complete.");
            }

            @Override
            public void onError(Throwable t) {
                System.out.println(t.getMessage());
            }

            @Override
            public void onNext(String s) {
                test.publishToQueue(s).subscribe(new Observer<Boolean>() {

                    @Override
                    public void onNext(Boolean b) {
                        if (b) {
                            System.out.println("Successfully published.");
                        }
                    }

                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable arg0) {
                    }
                });
            };
        });
        System.out.println("---END---");
    }

    public Observable<String> getFromDB() {

        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 30; i++) {
            list.add(Integer.toString(i));
        }
        return Observable.from(list).doOnNext(new Action1<String>() {
            @Override
            public void call(String temp) {
                if (temp.contains("2")) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

    }

    public Observable<Boolean> publishToQueue(String s) {

        return Observable.defer(() -> {
            try {
                if (s.contains("7")) {
                    Thread.sleep(700);
                }
                System.out.println("Published:: " + s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Observable.just(true);
        });
    }
}

Suppose I get a list from the DB asynchronously and want to post it to the queue,. I have used an Observable returned from getFromDB and have subscribed to it which mimics the data I get from DB. Every time I get the data from DB , I want to push it to a queue using publishToQueue which also returns an Observable . I wanted to make the queue call also asynchronous. Now on positive acknowledgement from the queue such as the Boolean which I am returning ( Observable<Boolean> ), I want to print something.

So basically I just want both the processes to be asynchronous. For every data from DB, I push it to the Queue asynchronously.

I have added Thread.sleep() in both the methods, db call and queue so as to mimic a delay and to test the asynchronous operations. I think this is what causing the problem. But I also tried Obseravable.delay() but that doesn't even produce any output.

Please help me understand how this works and how I can make it work as I want it to.

You have to specified subscribeOn value.

Observable.just("one", "two", "three", "four", "five")
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(/* an Observer */);

http://reactivex.io/documentation/operators/subscribeon.html

By default, RxJava is synchronous . It means that everything will be perform in the same thread (and the current thread), by default. You can perform tasks in another thread thanks to observeOn / subscribeOn methods, or using some operators that perform tasks in another job (because it use another scheduler, like delay , interval , ...)

In your example, you have to explitly set in which scheduler the subscription will pe performed. (here, in which thread Observable.from will emit your list)

test.getFromDb()
    .subscribeOn(Schedulers.io())
    .subscribe();

Then you can use the flatMap operator and calling your publishToQueue method. This method will be executed in the previous scheduler, but you can force it to use another scheduler, thanks to observeOn method. Everything after the observeOn method will be executed in another thread.

 test.fromDb()
     .subscribeOn(Schedulers.io())
     .observeOn(Schedulers.computation())
     .flatMap(l -> test.publishToqueue(l))
     .subscribe();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM