简体   繁体   中英

Realm - implementing asynchronous queue

I have a dagger-singleton-wrapper handling my basic Realm requests. One of which looks like this:

public void insertOrUpdateAsync(final List<RealmMessage> messages, @Nullable final OnInsertListener listener) {
    Realm instance = getRealmInstance();
    instance.executeTransactionAsync(realm -> {
                List<RealmMessage> newMessages = insertOrUpdateMessages(realm, messages);
            },
            () -> success(listener, instance),
            error -> error(listener, error, instance));
}

private List<RealmMessage> insertOrUpdateMessages(@NonNull Realm realm, @NonNull final List<RealmMessage> messages) {
    ...
    return realm.copyToRealmOrUpdate(unattendedMessages);
}

Which works great.

However there is a corner case where - long story short - I launch insertOrUpdateAsynch() many, many times. And after some requests I get this:

Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@b7b848 rejected from io.realm.internal.async.RealmThreadPoolExecutor@80f96e1[Running, pool size = 17, active threads = 17, queued tasks = 100, completed tasks = 81]

My question is: how should I handle this without rebuilding whole application flow. My idea was to queue incoming requests via RxJava. Am I right? Which operators should I consider and educate myself?

Or am I approaching this in a completely wrong way? From most of my googling I've noticed that mostly the problem is in launching method like mine in a loop. I'm not using any. In my case problem is that this method is launched by multiple responses, and changing that is kind of impossible because of the current backend implementation.

If you do not want to redesign your application you may use a counting semaphore. You will see that two Threads will instantly acquire the the lock. The other thread will block until some call will release one lock. It is not recommanded to use acquire() without an Timeout.

In order to use RxJava you would have to change the design of your application and rate-limiting in RxJava is not that easy, because it is all about throughoutput.

private final Semaphore semaphore = new Semaphore(2);

@Test
public void name() throws Exception {
    Thread t1 = new Thread(() -> {
        doNetworkStuff();
    });
    Thread t2 = new Thread(() -> {
        doNetworkStuff();
    });
    Thread t3 = new Thread(() -> {
        doNetworkStuff();
    });

    t1.start();
    t2.start();
    t3.start();

    Thread.sleep(1500);
}

private void doNetworkStuff() {
    try {
        System.out.println("enter doNetworkStuff");

        semaphore.acquire();

        System.out.println("acquired");

        Thread.sleep(1000);

    } catch (InterruptedException e) {
        e.printStackTrace(); // Don't do this!!
    } finally {
        semaphore.release();
    }
}

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