أساسيات Channel: send وreceive وclose
أنشئ القنوات وأرسل القيم واستقبلها وأغلقها بطريقة صحيحة.
أساسيات Channel: send وreceive وclose درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ما هي Channel؟
إن Channel بدائية من بدائيات coroutine للتواصل بين coroutine، وتشبه قائمة انتظار حاجزة لكنها تعلّق التنفيذ بدلًا من حجبه. فكّر فيها على أنها أنبوب: يرسل أحد الطرفين وتستقبل الجهة الأخرى.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val channel = Channel<Int>()
launch {
for (i in 1..5) channel.send(i)
channel.close()
}
for (x in channel) println(x) // 1 2 3 4 5
}send وreceive
تعلّق send(value) التنفيذ حتى يصبح المستقبل جاهزًا. وتعلّق receive() التنفيذ حتى تتوفر قيمة.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val ch = Channel<String>()
launch {
ch.send("ping")
println("sent")
}
val msg = ch.receive()
println("received: $msg")
}إغلاق Channel
تشير channel.close() إلى أنه لن تُرسل قيم أخرى. ويحصل المستقبلون على القيم المتبقية المخزنة مؤقتًا، ثم تنتهي حلقة for.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val ch = Channel<Int>(3)
launch {
repeat(3) { ch.send(it) }
ch.close() // signal done
}
for (v in ch) println(v) // 0 1 2, then loop ends
println("Channel consumed")
}isClosedForSend / isClosedForReceive
تحقق من حالة القناة باستخدام isClosedForSend، أي لا يُسمح بإرسال المزيد، وisClosedForReceive، أي استُهلكت جميع القيم.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val ch = Channel<Int>()
launch {
ch.send(1)
ch.close()
}
println(ch.receive())
println("isClosedForReceive: ${ch.isClosedForReceive}")
}الباني produce
يُعد produce { } باني coroutine ينشئ coroutine منتجة ويعيد ReceiveChannel. وتُغلق القناة تلقائيًا عند انتهاء الكتلة.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun CoroutineScope.squares(n: Int) = produce<Int> {
for (i in 1..n) send(i * i)
}
fun main() = runBlocking {
val sq = squares(5)
for (v in sq) println(v) // 1 4 9 16 25
}امتداد consumeEach
يكرّر consumeEach { } على عناصر القناة ويلغيها عند طرح الكتلة لاستثناء، مما يمنع تسرّب الموارد.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val ch = produce<String> {
send("a"); send("b"); send("c")
}
ch.consumeEach { println(it) }
}tryReceive وtrySend
بدائل لا تعلّق التنفيذ: يعيد trySend وtryReceive قيمة ChannelResult فورًا من دون تعليق.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val ch = Channel<Int>(1)
val sendResult = ch.trySend(42)
println("Sent: ${sendResult.isSuccess}")
val recvResult = ch.tryReceive()
println("Got: ${recvResult.getOrNull()}")
}التوزيع إلى الخارج: مستهلكون متعددون
يمكن لعدة coroutine الاستقبال من القناة نفسها، مما يوزّع العمل بينها؛ وهذا نمط التوزيع إلى الخارج.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val tasks = produce { repeat(6) { send(it) } }
repeat(3) { worker ->
launch {
for (task in tasks) {
println("Worker $worker: task $task")
}
}
}
}الدمج إلى الداخل: منتجون متعددون
يمكن لعدة coroutine الإرسال إلى القناة نفسها، مما يدمج نواتجها؛ وهذا نمط الدمج إلى الداخل.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val results = Channel<String>()
repeat(3) { i ->
launch { results.send("result-$i") }
}
launch {
repeat(3) { println(results.receive()) }
results.close()
}
}نمط خط الأنابيب
اربط القنوات في خط أنابيب، بحيث تقرأ كل مرحلة من قناة وتكتب إلى أخرى؛ وهذا مناسب جدًا لسير عمل معالجة البيانات.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun CoroutineScope.numbers() = produce { for (i in 1..5) send(i) }
fun CoroutineScope.doubled(input: ReceiveChannel<Int>) = produce { for (v in input) send(v * 2) }
fun main() = runBlocking {
val nums = numbers()
val doubled = doubled(nums)
for (v in doubled) println(v) // 2 4 6 8 10
coroutineContext.cancelChildren()
}Channel مقابل Flow
تُعد Channel ساخنة وذات حالة، فهي موجودة بصورة مستقلة عن الاستهلاك. أما Flow فباردة وتصريحية، إذ يُعاد تشغيلها عند كل عملية تجميع. فضّل Flow لتدفقات البيانات، واستخدم Channel للتواصل بين المنتج والمستهلك.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
// Flow (cold): each collect() re-runs the block
// Channel (hot): shared; multiple receivers share the same stream
fun main() = runBlocking { println("Flow = cold; Channel = hot") }تحقق سريع
ماذا يحدث عند استدعاء channel.close()؟
مراجعة
يعلّق كل من send وreceive التنفيذ حتى يصبح الطرف الآخر جاهزًا. وتشير close() إلى اكتمال العمل. استخدم produce للمنتجين الذين يُغلقون أنفسهم، وconsumeEach للتكرار الآمن، واستخدم القنوات لأنماط التوزيع إلى الخارج والدمج إلى الداخل.
الأسئلة الشائعة
هل درس «أساسيات Channel: send وreceive وclose» مجاني؟
نعم — نص درس «أساسيات Channel: send وreceive وclose» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ماذا ستتعلم في «أساسيات Channel: send وreceive وclose»؟
أنشئ القنوات وأرسل القيم واستقبلها وأغلقها بطريقة صحيحة. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟
لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أساسيات Channel: send وreceive وclose»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟
نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات Channel: send وreceive وclose
- أنواع Channel: Rendezvous وBuffered وConflated وUnlimited
- Mutex وSemaphore للحالة المشتركة
- Actors وإدارة الحالة المنظّمة