العمل مع قوائم انتظار المهام في Kotlin: عمليًا

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

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

ابدأ الدورة

مقدمة: لماذا نحتاج إلى قوائم انتظار المهام في Kotlin؟

\n

تتطلب التطبيقات الحديثة بشكل متزايد معالجة متوازية للبيانات، وعمليات خلفية، واستدعاءات غير متزامنة. بدون إدارة ذكية للمهام، قد يواجه كودك مشاكل في الأداء، أو تسربًا للذاكرة، أو "تجميد" الواجهة. قوائم انتظار المهام في Kotlin ليست مجرد تجريد، بل هي أداة قوية تساعد في تنظيم تنفيذ العمل بالترتيب الصحيح، مع التحكم في عدد الخيوط والأولويات.

\n

في هذه المقالة، سنستعرض الأساليب العملية لتنفيذ قوائم انتظار المهام في Kotlin: من ThreadPoolExecutor الكلاسيكي إلى coroutines مع موزعيها المرنين. سترى كيفية تطبيق هذه التقنيات في المشاريع الحقيقية، وستحصل على أمثلة جاهزة للكود.

\n\n

1. النهج الكلاسيكي: ThreadPoolExecutor و BlockingQueue

\n

توفر المكتبة القياسية لجافا (وكذلك Kotlin كلغة JVM) فئة قوية ThreadPoolExecutor. وهي تدير مجموعة من الخيوط وتستخدم قائمة انتظار داخلية محظورة لتخزين المهام المنتظرة.

\n\n

إنشاء قائمة انتظار بعدد ثابت من الخيوط

\n

أبسط حالة هي مجموعة بعدد ثابت من الخيوط. يتم وضع جميع المهام التي لا يمكن تنفيذها فورًا في قائمة انتظار LinkedBlockingQueue.

\n\n
import java.util.concurrent.Executors\nimport java.util.concurrent.TimeUnit\n\nfun main() {\n    val executor = Executors.newFixedThreadPool(3)\n\n    for (i in 1..10) {\n        executor.submit {\n            println("المهمة $i يتم تنفيذها في الخيط ${Thread.currentThread().name}")\n            Thread.sleep(1000)\n        }\n    }\n\n    executor.shutdown()\n    executor.awaitTermination(1, TimeUnit.MINUTES)\n    println("جميع المهام اكتملت")\n}\n
\n

يوضح هذا الكود قائمة انتظار أساسية: يتم إرسال المهام إلى المجموعة، وإذا كانت جميع الخيوط مشغولة، فإنها تنتظر في قائمة الانتظار.

\n\n

قائمة انتظار ذات أولوية: PriorityBlockingQueue

\n

في بعض الأحيان، يلزم تنفيذ المهام العاجلة قبل البقية. لهذا نستخدم PriorityBlockingQueue مع مقارن مخصص.

\n\n
import java.util.concurrent.PriorityBlockingQueue\nimport java.util.concurrent.ThreadPoolExecutor\nimport java.util.concurrent.TimeUnit\n\ndata class PriorityTask(val priority: Int, val name: String) : Comparable<PriorityTask> {\n    override fun compareTo(other: PriorityTask): Int = other.priority - this.priority\n}\n\nfun main() {\n    val queue = PriorityBlockingQueue<Runnable>(10) { r1, r2 ->\n        val t1 = (r1 as PriorityTaskWrapper).task\n        val t2 = (r2 as PriorityTaskWrapper).task\n        t1.compareTo(t2)\n    }\n\n    val executor = ThreadPoolExecutor(2, 4, 1, TimeUnit.SECONDS, queue)\n\n    class PriorityTaskWrapper(val task: PriorityTask, val action: () -> Unit) : Runnable {\n        override fun run() = action()\n    }\n\n    for (i in 1..5) {\n        val priority = if (i % 2 == 0) 10 else 1\n        executor.submit(PriorityTaskWrapper(PriorityTask(priority, "المهمة $i")) {\n            println("جارٍ التنفيذ: ${PriorityTask(priority, "المهمة $i")}")\n            Thread.sleep(500)\n        })\n    }\n\n    executor.shutdown()\n    executor.awaitTermination(1, TimeUnit.MINUTES)\n}\n
\n

هنا، سيتم تنفيذ المهام ذات priority = 10 قبل تلك ذات priority = 1، حتى لو تمت إضافتها لاحقًا.

\n\n

2. قوائم انتظار المهام باستخدام coroutines (kotlinx.coroutines)

\n

تقدم Kotlin الحديثة coroutines - وهي خيوط خفيفة الوزن تسمح ببناء قوائم انتظار غير متزامنة دون إدارة مباشرة للخيوط. الأداة الرئيسية هي Channel و Dispatchers.

\n\n

قائمة انتظار بسيطة عبر Channel

\n

Channel هو نظير لقائمة الانتظار المحظورة، ولكن لـ coroutines. يسمح بنقل المهام بأمان بين coroutines.

\n\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.channels.Channel\n\nsuspend fun processTas                

المدونات

توصيات الكتب