التزامن وتعدد الخيوط في Kotlin: الكوروتينات، الخيوط والأمثلة العملية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة
```html

التزامن وتعدد الخيوط في Kotlin: من النظرية إلى التطبيق

تتطلب التطبيقات الحديثة أداءً سريعًا وسريع الاستجابة. سواء كان الأمر يتعلق بتحميل البيانات من الشبكة، أو معالجة مصفوفات كبيرة، أو العمل مع واجهة المستخدم — لا يمكن الاستغناء عن التزامن وتعدد الخيوط. Kotlin، كونه لغة حديثة لـ JVM و Android والمشاريع متعددة المنصات، يقدم أدوات مرنة لحل هذه المهام. في هذه المقالة، سنستعرض الأساليب الرئيسية: من الخيوط التقليدية إلى coroutines خفيفة الوزن، وسنوضح كيفية كتابة كود فعال.

1. الخيوط (Threads) في Kotlin: الأسلوب التقليدي

الخيوط هي آلية أساسية للتنفيذ المتوازي، موروثة من Java. في Kotlin، يمكنك إنشاء خيوط بنفس الطريقة كما في Java، ولكن مع بناء جملة أكثر إيجازًا.

مثال بسيط لبدء خيط:

fun main() {
    thread {
        println("تم بدء الخيط: ${Thread.currentThread().name}")
        Thread.sleep(1000)
        println("تم إنهاء الخيط")
    }
    println("الخيط الرئيسي: ${Thread.currentThread().name}")
    Thread.sleep(2000)
}

ومع ذلك، فإن للخيوط عيوبًا: فهي ثقيلة الوزن (يستهلك كل خيط حوالي 1 ميجابايت من الذاكرة)، وعددها محدود، وتبديل السياق مكلف. بالنسبة للتطبيقات الحديثة التي تحتوي على آلاف المهام المتوازية، فإن الخيوط ليست الخيار الأفضل. وهنا تأتي coroutines للإنقاذ.

2. coroutines: البديل خفيف الوزن

Coroutines هي الميزة الرئيسية في Kotlin للتزامن. تعمل فوق الخيوط، ولكنها تستخدم موارد أقل. يمكن لخيط واحد تنفيذ آلاف من coroutines، مع إيقافها مؤقتًا واستئنافها دون حظر.

للبدء، أضف التبعية في build.gradle.kts:

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
}

مثال على coroutine بسيط:

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(1000L) // تأخير غير محظور
        println("العالم من coroutine!")
    }
    println("مرحبًا من coroutine الرئيسي")
    delay(2000L)
}

هنا، launch يبدأ coroutine جديد، و delay يوقفه مؤقتًا دون حظر الخيط. يتم استخدام runBlocking لحظر الخيط الرئيسي حتى اكتمال جميع coroutines (يُستخدم عادةً فقط في main والاختبارات).

2.1. دوال Suspend

الكلمة المفتاحية suspend تسمح بإيقاف تنفيذ الدالة مؤقتًا دون حظر الخيط. هذا هو أساس البرمجة غير المتزامنة في Kotlin.

suspend fun fetchUser(): String {
    delay(500L) // محاكاة طلب شبكة
    return "User123"
}

fun main() = runBlocking {
    val user = fetchUser()
    println("تم الحصول على المستخدم: $user")
}

2.2. Async و Deferred للمهام المتوازية

إذا كنت بحاجة إلى تنفيذ عدة مهام بالتوازي وانتظار نتائجها، استخدم async و Deferred:

fun main() = runBlocking {
    val time = measureTimeMillis {
        val user = async { fetchUser() }
        val profile = async { fetchProfile() }
        println("النتائج: ${user.await()}, ${profile.await()}")
    }
    println("وقت التنفيذ: $time مللي ثانية")
}

suspend fun fetchUser(): String {
    delay(500)
    return "User"
}

suspend fun fetchProfile(): String {
    delay(500)
    return "Profile"
}

يتم تنفيذ كلتا المهمتين بالتوازي، مما يقلل الوقت الإجمالي.

3. موزعو coroutines (Dispatchers)

يحدد الموزعون الخيوط التي سيتم تنفيذ coroutines عليها. الأنواع الرئيسية:

  • Dispatchers.Default — للمهام كثيفة الاستخدام لوحدة المعالجة المركزية (الافتراضي).
  • Dispatchers.IO — لعمليات الإدخال والإخراج (الشبكة، الملفات).
  • Dispatchers.Main — لخيط واجهة المستخدم (Android, JavaFX).
  • ```

المدونات

توصيات الكتب