← Назад к вопросам
Как проверить параллельность выполнения
2.0 Middle🔥 62 комментариев
#Многопоточность и асинхронность#Тестирование
Комментарии (2)
🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Проверка параллельности выполнения в Android
Проверка параллельности выполнения в Android — это комплексная задача, так как она затрагивает многопоточность, асинхронные операции и взаимодействие с UI-потоком. Вот основные подходы и инструменты для проверки.
Основные принципы параллельности в Android
- Главный поток (UI-поток) — обрабатывает обновления интерфейса и события пользователя. Должен оставаться отзывчивым.
- Фоновые потоки — используются для долгих операций (сеть, БД, вычисления). Создаются через
Thread,ExecutorService,CoroutineDispatcherилиRxJava Schedulers. - Синхронизация — управление доступом к общим ресурсам из нескольких потоков (через
synchronized,Atomic-классы,Mutexв Kotlin).
Методы проверки параллельности
1. Логирование и отладка
- Добавление идентификаторов потоков в логи:
Log.d("Concurrency", "Действие в потоке: ${Thread.currentThread().name}")
- Точки останова в Debugger с условиями по имени потока.
2. Инструменты Android Studio
- Android Profiler → вкладка CPU → запись выполнения с детализацией по потокам.
- Layout Inspector — проверка блокировок UI из-за долгих операций в главном потоке.
3. Написание юнит-тестов с проверкой потоков
Для JUnit-тестов используйте проверки на выполнение в фоновом потоке:
@Test
fun testBackgroundOperation() {
var isMainThread = false
val latch = CountDownLatch(1)
GlobalScope.launch(Dispatchers.IO) {
isMainThread = Looper.getMainLooper() == Looper.myLooper()
latch.countDown()
}
latch.await(2, TimeUnit.SECONDS)
assertFalse(isMainThread)
}
4. Интеграционные тесты с Espresso и Idling Resources
IdlingResource — механизм Espresso для ожидания завершения фоновых задач:
class MyIdlingResource : IdlingResource {
override fun getName() = "MyBackgroundTask"
override fun isIdleNow() = !isTaskRunning // Флаг завершения задачи
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
this.callback = callback
}
fun onTaskFinished() {
callback?.onTransitionToIdle()
}
}
5. Стресс-тестирование и детекция гонок данных
- Повторение операций в циклах (1000+ итераций) для выявления редких состояний гонки.
- Использование
Collections.synchronizedList()илиConcurrentHashMapс последующей проверкой целостности данных. - Инструмент
ThreadSanitizer(TSan) — доступен в нативных (C/C++) слоях.
6. Проверка корутин (Kotlin Coroutines)
Для корутин используйте тестовый диспетчер TestCoroutineDispatcher или runTest в kotlinx-coroutines-test:
@Test
fun testParallelCoroutines() = runTest {
val dispatcher = StandardTestDispatcher(testScheduler)
val results = mutableListOf<Int>()
val job1 = launch(dispatcher) { results.add(1) }
val job2 = launch(dispatcher) { results.add(2) }
joinAll(job1, job2)
assertEquals(listOf(1, 2), results) // Порядок может быть разным
}
7. Мониторинг deadlock и ANR
- Анализ логов ANR (
/data/anr/traces.txt) для обнаружения взаимных блокировок. - Использование
StrictModeдля детекции операций на UI-потоке:
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectNetwork()
.detectDiskReads()
.penaltyLog() // Или penaltyDeath() для тестов
.build())
Типичные проблемы и их проверка
| Проблема | Метод проверки |
|---|---|
| Утечка потока | Проверка через LeakCanary + мониторинг количества потоков в Profiler. |
| Гонка данных | Стресс-тесты с увеличением нагрузки и проверкой атомарности. |
| Блокировка UI | Запуск долгой операции и проверка отклика интерфейса (Espresso + IdlingResource). |
| Некорректная отмена | Тестирование отмены Job в корутинах или Disposable в RxJava. |
Рекомендации
- Всегда документируйте предполагаемую модель параллельности для каждого компонента.
- Пишите детерминированные тесты, используя тестовые диспетчеры для корутин или
TestSchedulerдля RxJava. - Профилируйте приложение на слабых устройствах, где проблемы параллельности проявляются чаще.
Правильная проверка параллельности требует комбинации статического анализа (код-ревью), динамического тестирования (инструменты профилирования) и написания специализированных тестов, моделирующих конкурентный доступ.