مقدمة في البرمجة غير المتزامنة في Kotlin
تتطلب التطبيقات الحديثة أداءً عاليًا واستجابة سريعة. تتيح البرمجة غير المتزامنة تنفيذ العمليات الطويلة (طلبات الشبكة، قراءة الملفات، العمل مع قواعد البيانات) دون حظر سلسلة التنفيذ الرئيسية. في Kotlin، يتم استخدام آلية قوية وأنيقة لهذا الغرض — الروتينات المتزامنة (coroutines).
على عكس سلاسل التنفيذ التقليدية (threads)، فإن الروتينات المتزامنة خفيفة الوزن، وتُدار على مستوى اللغة، ولا تتطلب موارد نظام ضخمة. وهذا يجعلها أداة مثالية لكتابة كود غير متزامن يسهل قراءته وصيانته. في هذا الدليل، سنشرح المفاهيم الأساسية للبرمجة غير المتزامنة في Kotlin من الصفر.
1. أساسيات الروتينات المتزامنة: ما هي وكيف تعمل؟
الروتين المتزامن هو مثيل لعملية حسابية قابلة للإيقاف المؤقت (suspendable). يمكن إيقافها مؤقتًا في نقطة معينة من الكود واستئنافها في نقطة أخرى، دون حظر سلسلة التنفيذ. للعمل مع الروتينات المتزامنة، يجب إضافة مكتبة kotlinx.coroutines.
إضافة التبعية
أضف إلى ملف build.gradle.kts:
dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")}أول روتين متزامن
لتشغيل روتين متزامن، يُستخدم المُنشئ launch. يقوم بتشغيل روتين متزامن جديد في الخلفية.
import kotlinx.coroutines.*
fun main() = runBlocking { // runBlocking يحظر السلسلة الرئيسية لانتظار الروتينات المتزامنة println("البداية: ${Thread.currentThread().name}")
launch { // تشغيل روتين متزامن جديد delay(1000L) // إيقاف مؤقت لمدة ثانية واحدة (لا يحظر السلسلة!) println("الروتين المتزامن: ${Thread.currentThread().name}") }
println("النهاية: ${Thread.currentThread().name}")}المخرجات:
البداية: mainالنهاية: mainالروتين المتزامن: mainلاحظ: delay هي دالة إيقاف مؤقت (suspend-function) توقف الروتين المتزامن مؤقتًا، لكنها لا تحظر سلسلة التنفيذ. بينما "ينام" الروتين المتزامن، يمكن للسلسلة تنفيذ كود آخر.
2. دوال الإيقاف المؤقت (Suspend-functions): اللبنات الأساسية لعدم التزامن
دالة الإيقاف المؤقت هي دالة يمكن إيقافها مؤقتًا واستئنافها لاحقًا. يمكن استدعاء هذه الدوال فقط من دوال إيقاف مؤقت أخرى أو من روتين متزامن. يتم تمييزها بالكلمة المفتاحية suspend.
مثال على دالة إيقاف مؤقت
import kotlinx.coroutines.*
suspend fun fetchData(): String { delay(2000L) // محاكاة طلب شبكة طويل return "تم استلام البيانات"}
fun main() = runBlocking { println("طلب البيانات...") val result = fetchData() // استدعاء دالة إيقاف مؤقت من روتين متزامن println(result)}التنفيذ المتوازي باستخدام async/await
إذا كنت بحاجة إلى تنفيذ عدة مهام بالتوازي، استخدم المُنشئ async. يقوم بإرجاع Deferred — كائن يخزن النتيجة المستقبلية. يمكن الحصول على النتيجة باستخدام await().
import kotlinx.coroutines.*
suspend fun loadUser(): String { delay(1000L) return "المستخدم: إيفان"}
suspend fun loadPosts(): String { delay(1500L) return "المقالات: أخبار، مقالات"}
fun main() = runBlocking { val time = measureTimeMillis { val userDeferred = async { loadUser() } val postsDeferred = async { loadPosts() }
println(userDeferred.await()) println(postsDeferred.await()) } println("الوقت الإجمالي: $time مللي ثانية") // ~1500 مللي ثانية (أقصى وقت من الاثنين)}بدون async، كانت المهام ستنفذ بشكل تسلسلي وتستغرق ~2500 مللي ثانية. التنفيذ المتوازي قلص الوقت إلى ~1500 مللي ثانية.
3. الموزعون (Dispatchers): إدارة سلاسل التنفيذ
الموزع يحدد على أي سلسلة تنفيذ أو مجموعة سلاسل تنفيذ سيتم تنفيذ