Realm-java: Frequent updates of the Realm database crash

Created on 31 Jan 2018  ·  7Comments  ·  Source: realm/realm-java

I have a problem. I need to call the following code frequently in the main thread:

public static void removeAll(final String name) {
        Realm realm = Realm.getDefaultInstance();
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                RealmResults<Focus> focuses = realm.where(Focus.class)
                                                   .equalTo("name", name)
                                                   .findAll();
                if(focuses != null) {
                    boolean result = focuses.deleteAllFromRealm();
                    Log.e(TAG,"size:"+focuses.size()+",result:"+result);
                }
            }
        });
    }

Then,My task failed, and the exception was as follows:

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@246169a rejected from io.realm.internal.async.RealmThreadPoolExecutor@7d6bbcb[Running, pool size = 17, active threads = 17, queued tasks = 100, completed tasks = 0]
                                                       at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2049)
                                                       at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:814)
                                                       at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1360)
                                                       at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:89)
                                                       at io.realm.internal.async.RealmThreadPoolExecutor.submitTransaction(RealmThreadPoolExecutor.java:111)
                                                       at io.realm.Realm.executeTransactionAsync(Realm.java:1387)
                                                       at io.realm.Realm.executeTransactionAsync(Realm.java:1322)
                                                       at com.evomotion.apiserver.model.FocusDao.removeAll(FocusDao.java:66)

I think it is the reason for the use of the thread pool. How should I modify it?

T-Help

Most helpful comment

@Harlber have a dedicated background thread of your own via Executors.newSingleThreadedPool() (singleton instance of it) and run the transaction synchronously on that thread.

All 7 comments

The Realm thread pool has a limit of 100 tasks. It appears you are calling removeAll(name) in some kind of loop that hits that limit. This is really in-efficient and the normal AsyncTask pool on Android has a similar limit.

The work-around is to move transaction outside the loop. In this case, it can be done by sending all names that should be deleted at once, like this:

// Current approach
for (String name : getNames() {
  removeAll(name);
}

// New approach
removeAll(getNames());

public static void removeAll(final String[] names) {
        Realm realm = Realm.getDefaultInstance();
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                RealmResults<Focus> focuses = realm.where(Focus.class)
                                                   .in("name", names)
                                                   .findAll();
                if(focuses != null) {
                    boolean result = focuses.deleteAllFromRealm();
                    Log.e(TAG,"size:"+focuses.size()+",result:"+result);
                }
            }
        });
}

I assume the above solved your issue. If not, feel free to reopen. Closing

I have the same problem while frequently insert. (IM app)
Could Realm remove this limit,or make task no-block but in queue(cache it)?
@cmelchior

@Harlber If you are running into this it means you are doing something non-optimal like creating transactions in a loop. If we removed the limit you would just run into problems elsewhere.

In my case, sometimes receive messages frequently. And I have to insert messages one by one. And the database crash.As your word, the limit makes a safety barrier, but what can I do to solve my case?
Thanks in advance!

@Harlber have a dedicated background thread of your own via Executors.newSingleThreadedPool() (singleton instance of it) and run the transaction synchronously on that thread.

Thanks !
In the comment, Creates a RealmThreadPool with only 1 thread. This is primarily useful for testing.
I thought this was designed for unit testing, Just like @VisibleForTesting
Thank you very much for your suggestion!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wyvern610 picture wyvern610  ·  3Comments

CNyezi picture CNyezi  ·  3Comments

wezley98 picture wezley98  ·  3Comments

AAChartModel picture AAChartModel  ·  3Comments

yuwu picture yuwu  ·  3Comments