Sobes.tech
Middle+

Kotlin-də çox iş parçacığı ilə necə işləyirsiniz?

sobes.tech Süni İntellekt

AI-dan cavab

Kotlin-də çoxlu ipliklərlə işləmək üçün əsasən korutinlər istifadə edirəm. Onlar ənənəvi ipliklərə nisbətən daha yüngül və çevik yanaşma təmin edir, əlavə xərcləri azaldır və paralel əməliyyatların idarə olunmasını sadələşdirir.

Korutinlərlə işləmək üçün əsas anlayışlar:

  • Suspend funksiyalar: Dayandırıla və davam etdirilə bilən funksiyalar. Onlar korutinlərdə asinxron əməliyyatların əsasını təşkil edir.
    suspend fun fetchData(): String {
        delay(1000) // Nümunə dayandırma
        return "Məlumat alındı"
    }
    
  • CoroutineScope: Korutinlərin həyat dövrünü müəyyən edir və onların ləğv edilməsini idarə etməyə imkan verir.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking { // Bloklayıcı icra üçün CoroutineScope
        launch { // Bu Scope-də yeni korutina yaradılması
            // Korutina kodu
        }
    }
    
  • Dispatcherlər (Dispatchers): Korutinanın işləyəcəyi iplik hovuzunu müəyyən edir.
    • Dispatchers.Default: CPU intensiv hesablamalar üçün.
    • Dispatchers.IO: Bloklayan I/O üçün (məsələn, şəbəkə, fayllar ilə işləmə).
    • Dispatchers.Main: UI ilə işləmək üçün (müvafiq platformalarda mövcuddur, məsələn Android).
    • Dispatchers.Unconfined: Müəyyən bir iplik hovuzuna bağlı deyil.
    import kotlinx.coroutines.*
    
    suspend fun doSomethingAsync() {
        withContext(Dispatchers.IO) { // I/O dispatcher-ə keçid
            // Bloklayan əməliyyatın yerinə yetirilməsi
        }
    }
    
  • Korutinlərin qurucuları (Coroutine Builders): Korutinləri başlatmaq üçün funksiyalar.
    • launch: Korutinanı başlatır və Job qaytarır, onu ləğv etmək üçün istifadə edilə bilər.
    • async: Korutinanı başlatır və Deferred qaytarır, nəticəni almağa imkan verir (await()).
    import kotlinx.coroutines.*
    
    suspend fun example() {
        val job = launch {
            // Paralel tapşırıq
        }
    
        val deferredResult = async {
            // Nəticə qaytaran tapşırıq
            "Nəticə"
        }
    
        job.cancel() // Tapşırığın ləğvi
        val result = deferredResult.await() // Nəticənin alınması
    }
    

Ümumi resurslara girişin sinxronizasiyası üçün kotlinx.coroutines.sync paketindən alətlərdən istifadə edirəm, məsələn, Mutex və ya Semaphore.

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*

val mutex = Mutex()
var counter = 0

suspend fun incrementCounter() {
    mutex.withLock { // Mutex bloklama, ümumi resursa girişdən əvvəl
        counter++
    }
}

Bəzi xüsusi hallarda, aşağı səviyyədə ipliklərin birbaşa idarə olunması lazım gəldikdə, java.util.concurrent paketindən siniflər və ya birbaşa ThreadRunnable siniflərindən istifadə edə bilərəm, baxmayaraq ki, bu, korutinlərdən çox daha az istifadə olunur.

Korutinlərin ən böyük üstünlükləri:

Xüsusiyyət Korutinlər Ənənəvi ipliklər
Yüngüllük Yüngül, çox sayda bir iplikdə işləyə bilər Çəkili, hər iplik resurs tələb edir
Keçid Kooperativ (suspend/resume) Zorunlu (OS planlayıcısı)
Ləğv Asan və strukturlaşdırılmış Çətin, kəsilmə idarəetməsi tələb edir
Debug Rahat, yığım izləri saxlanılır Çətin ola bilər
Strukturlaşdırma Strukturlaşdırılmış konkurrentlik dəstəkləyir Daha az strukturlaşdırılmış

Korutinləri seçirəm, çünki onlar effektivdir, asinxron kod yazmağı sadələşdirir və oxunaqlılığı artırır, xüsusən də mürəkkəb asinxron əməliyyatların ardıcıllığında.