🕹️ Kotlin’de Eşzamanlılık (Concurrency)

Gorkem KARA
4 min readAug 5, 2024

--

English: https://gorkemkara.medium.com/%EF%B8%8F-concurrency-in-kotlin-2f61eb69d8b4

Eşzamanlılık, bir programın aynı anda birden fazla iş parçacığını çalıştırabilme yeteneğidir. Bu, büyük ve karmaşık işlemleri daha verimli bir şekilde yürütmek için önemlidir. Kotlin, eşzamanlılık yönetimi için çeşitli araçlar sunar. Bu makalede, Kotlin’de eşzamanlılık konusunu ve temiz kod standartlarına uygun eşzamanlılık yönetimini ele alacağız.

🎯 Neden Eşzamanlılık Kullanmalıyız?

Verimlilik Artışı: Birden fazla iş parçacığının aynı anda çalışabilmesi, işlemlerin daha hızlı tamamlanmasını sağlar.

Kullanıcı Deneyimi: Uzun süren işlemler kullanıcı arayüzünü kilitlemez, bu da daha iyi bir kullanıcı deneyimi sunar.

Kaynak Kullanımı: Sistem kaynaklarının daha verimli kullanılmasını sağlar.

🔧 Kotlin’de Eşzamanlılık Uygulamak

Aşağıda, Kotlin’de eşzamanlılık nasıl uygulanabileceğini gösteren bir örnek bulunmaktadır. Bu örnekte, bir web sitesinden veri çekme işlemi eşzamanlı olarak yapılacaktır.

Kötü Örnek: Eşzamanlılık Olmadan Veri Çekme

fun fetchData() {
val data1 = fetchFromServer("https://api.example.com/data1")
val data2 = fetchFromServer("https://api.example.com/data2")
println("Data1: $data1")
println("Data2: $data2")
}

fun fetchFromServer(url: String): String {
// Simüle edilen ağ gecikmesi
Thread.sleep(1000)
return "Response from $url"
}

Bu örnekte, veri çekme işlemleri ardışık olarak yapılmaktadır. Bu, toplam süreyi uzatır ve verimliliği düşürür.

İyi Örnek: Eşzamanlılık ile Veri Çekme

import kotlinx.coroutines.*

fun main() = runBlocking {
val data1 = async { fetchFromServer("https://api.example.com/data1") }
val data2 = async { fetchFromServer("https://api.example.com/data2") }
println("Data1: ${data1.await()}")
println("Data2: ${data2.await()}")
}

suspend fun fetchFromServer(url: String): String {
delay(1000) // Simüle edilen ağ gecikmesi
return "Response from $url"
}

Bu örnekte, async ve await kullanarak veri çekme işlemlerini eşzamanlı olarak gerçekleştiriyoruz. Bu, toplam süreyi azaltır ve verimliliği artırır.

Neden Coroutines Kullanmalıyız?

Yeni Android geliştiricileri için, coroutines kullanmamız gerektiğini anlamak, verimli ve temiz kod yazmanın anahtarlarından biridir. İşte bazı önemli nedenler:

Daha Basit Kod: Coroutines, asenkron kodun senkron kod gibi görünmesini ve davranmasını sağlar, bu da kodun okunmasını ve anlaşılmasını kolaylaştırır.

Hafif: Coroutines, iş parçacıklarından çok daha hafiftir. Minimal bellek kullanımıyla binlerce coroutine çalıştırabilirsiniz.

Yapısal Eşzamanlılık: Coroutines, belirli işlemler kapsamındaki coroutinelerin yaşam döngüsünü yönetmeye yardımcı olan yapısal eşzamanlılık sağlar, bu da bellek sızıntısı olasılığını azaltır.

Yerleşik Destek: Kotlin coroutines dili ile entegre edilmiştir ve Android geliştirmede mükemmel destek sağlar, kotlinx.coroutines gibi kütüphaneler ek özellikler ve yardımcı araçlar sunar.

Örnek: Asenkron Kodu Coroutines ile Basitleştirmek

Coroutines kullanmadan, asenkron işlemleri yönetmek karmaşık ve geri çağrılar (callbacks) gerektirebilir:

fun fetchData(callback: (String) -> Unit) {
Thread {
val data = fetchFromServer("https://api.example.com/data")
callback(data)
}.start()
}

Coroutines kullanmak bunu basitleştirir:

import kotlinx.coroutines.*

fun main() = runBlocking {
val data = fetchFromServer("https://api.example.com/data")
println(data)
}

suspend fun fetchFromServer(url: String): String {
delay(1000)
return "Response from $url"
}

🎨 Kodun Kullanımı

Aşağıda, bu sınıfların nasıl kullanılacağına dair bir örnek bulunmaktadır:

fun main() = runBlocking {
val featureToggle = FeatureToggle()
val userInterface = UserInterface(featureToggle)

userInterface.render()
}

class UserInterface(private val featureToggle: FeatureToggle) {
fun render() {
if (featureToggle.isNewUIEnabled()) {
// Yeni UI kodu
println("Rendering new UI")
} else {
// Eski UI kodu
println("Rendering old UI")
}
}
}

class FeatureToggle {
private val features = mapOf(
"newUI" to true // Özellik anahtarı durumları buradan yönetilir
)

fun isNewUIEnabled(): Boolean {
return features["newUI"] ?: false
}
}

Bu yapı, özellik anahtarlarını yönetmeyi ve yeni özellikleri kademeli olarak kullanıma sunmayı kolaylaştırır.

Temiz Kod Standartlarına Uygun Eşzamanlılık

Eşzamanlılık uygularken dikkat edilmesi gereken bazı temiz kod prensipleri şunlardır:

1. Anlamlı İsimler Kullanın

İş parçacıkları ve eşzamanlı işlemler için anlamlı ve açıklayıcı isimler kullanmak, kodun okunabilirliğini artırır.

Kötü Örnek:

fun task1() { /* ... */ }
fun task2() { /* ... */ }

İyi Örnek:

fun fetchUserData() { /* ... */ }
fun fetchProductData() { /* ... */ }

2. İş Parçacıklarını Yönetmek İçin Coroutine Kütüphanesini Kullanın

Kotlin’in coroutine kütüphanesi, iş parçacıklarını yönetmeyi ve eşzamanlı işlemleri daha basit ve güvenli hale getirir.

Kötü Örnek:

Thread {
// İş parçacığı kodu
}.start()

İyi Örnek:

GlobalScope.launch {
// Coroutine kodu
}

3. Hata Yönetimi Ekleyin

Eşzamanlı işlemler sırasında oluşabilecek hataları düzgün bir şekilde ele almak, kodun güvenilirliğini artırır.

Örnek:

import kotlinx.coroutines.*

fun main() = runBlocking {
try {
val data1 = async { fetchFromServer("https://api.example.com/data1") }
val data2 = async { fetchFromServer("https://api.example.com/data2") }
println("Data1: ${data1.await()}")
println("Data2: ${data2.await()}")
} catch (e: Exception) {
println("Error fetching data: ${e.message}")
}
}

suspend fun fetchFromServer(url: String): String {
delay(1000) // Simüle edilen ağ gecikmesi
if (url.contains("error")) throw Exception("Simulated error")
return "Response from $url"
}

Sonuç

Kotlin’de eşzamanlılık, büyük ve karmaşık işlemleri daha verimli bir şekilde yönetmenizi sağlar. Anlamlı isimler kullanarak, coroutine kütüphanesini kullanarak ve hata yönetimi ekleyerek, temiz kod standartlarına uygun eşzamanlılık uygulayabilirsiniz. Bu prensipler, yazılım projelerinizde eşzamanlı işlemleri daha etkili hale getirecek ve kod kalitenizi artıracaktır.

Clean Code Cookbook’a göre, temiz kod iyi yapılandırılmış, özlü ve değişkenler, fonksiyonlar ve sınıflar için anlamlı isimler kullanır. En iyi uygulamaları ve tasarım kalıplarını takip eder, performans ve uygulama detaylarının üzerinde okunabilirlik ve davranışı tercih eder. Temiz kod yazarak ve testlerle kaplayarak, en kritik darboğazlara odaklanarak performansı artırabilirsiniz. Bu yaklaşım, erken optimizasyon için kodun okunabilirliğinden ve sürdürülebilirliğinden ödün vermemenizi sağlar.

Bu makaledeki kullanımların bir benzeri için github projesi: https://github.com/birdeveloper/kotlin_concurrency_project

Umarım bu makale, Kotlin’de eşzamanlılık uygulamanın yanı sıra temiz kod prensiplerini anlamanıza yardımcı olmuştur. Sorularınız, önerileriniz varsa veya bu konuyu daha fazla tartışmak isterseniz, lütfen benimle iletişime geçmekten çekinmeyin.

--

--