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?
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!
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.