简体   繁体   English

领域-实现异步队列

[英]Realm - implementing asynchronous queue

I have a dagger-singleton-wrapper handling my basic Realm requests. 我有一个匕首单包装器,处理基本的Realm请求。 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. 但是,有一个极端的情况-长话短说-我多次启动insertOrUpdateAsynch()。 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. 我的想法是通过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. 不建议在没有超时的情况下使用acquire()。

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. 为了使用RxJava,您将不得不更改应用程序的设计,而RxJava中的速率限制并不是那么容易,因为这全都与输出有关。

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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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