Что нужно помнить при многопоточности Realm DB
Realm - одна из лучших альтернатив SQLite DB в Android. Его действительно легко настроить, и с ним весело работать. Поскольку realm lazy загружает данные, их читать очень быстро.
У Realm есть свои болевые точки, самая большая из которых - многопоточность. Управляемые объекты области (объекты, которые читают из области) не могут передаваться между потоками, если вы не преобразовали их в POJO. Запись в область в некоторых случаях очень медленная (когда у вас есть слушатели для элемента, который вы изменяете).
Вот некоторые вещи, которые следует помнить при использовании области в нескольких потоках
Максимальный размер асинхронной очереди - 100
Довольно легко написать что-нибудь в области в асинхронном режиме, используя метод executeTransactionAsync, подобный этому
Вот в чем загвоздка. Существует ограничение на количество элементов, которые могут быть добавлены в эту очередь транзакций. Если количество транзакций, добавленных в очередь, больше 100, Realm DB выдаст ошибку. Поэтому, если вы записываете много элементов за один раз, убедитесь, что вы пишете в одной транзакции, а не добавляете ее как разные транзакции.
Вышеуказанный метод не рекомендуется. Лучше писать одной транзакцией.
Нужен обработчик темы
Для управления параллелизмом Realm использует MVCC (Multi-version Concurrency Control). Каждый поток получает моментальный снимок БД в тот конкретный момент времени, когда создается экземпляр области. При изменении данных моментальный снимок обновляется, и вы получаете самые свежие данные. Но снимок обновляется только в том случае, если у потока есть петлитель. Если у вас есть экземпляр области в потоке A, у которого нет цикла, и новая запись записывается в БД из потока B. Экземпляр области в потоке A не сможет увидеть новые данные.
Поэтому, если у вас есть экземпляр области, который будет открыт в течение длительного времени, лучше быть в потоке обработчика.
Если вам случайно понадобится экземпляр области в потоке без цикла, и вы хотите обновить моментальный снимок БД, вы можете использовать realm.refresh()
для обновления моментального снимка области.
Наличие нескольких экземпляров
Когда вы используете несколько экземпляров области, работающей в нескольких потоках, вы должны понимать связанные с этим затраты. Когда вы создаете новый экземпляр области, он занимает много памяти. Поэтому, если вы не закрываете область после того, как закончите с ней, или у вас есть большое количество потоков, использующих область одновременно. Есть вероятность, что вы можете получить исключение нехватки памяти. Следовательно, лучше иметь ограниченное количество экземпляров открытой области в любой момент времени.
Realm.getGlobalInstanceCount(Realm.getDefaultConfiguration())
можно использовать для определения количества активных экземпляров области.
Всегда используйте try with resources
в Java или use
в kotlin, чтобы закрыть экземпляр области после использования.
Вышеупомянутое - это некоторые вещи, которые следует помнить при использовании Realm в многопоточной среде.
~ Удачного кодирования ~