Coroutines (کوروٹینز) Kotlin میں غیر متوازن پروگرامنگ کے لیے ہلکے تھریڈ ہیں، جو kotlinx.coroutines لائبریری کے ذریعے دستیاب ہیں۔ JetBrains Kotlin Documentation, 2026 کے مطابق، Coroutines روایتی Thread کے برعکس، تھریڈ کو مسدود کیے بغیر فنکشن کے اجراء کو معطل کر سکتے ہیں۔ کوروٹینز ایک محدود تھریڈ پول پر چلتے ہیں، جو انہیں مقامی تھریڈ سے ہزار گنا ہلکا بناتا ہے۔ Kotlin Coroutines Android Jetpack، Retrofit، Room اور Android ماحولیاتی نظام کی دیگر مشہور لائبریریوں کے ساتھ مکمل طور پر ضم ہیں۔
اہم نکات
Coroutines Kotlin میں ایک غیر متوازن پروگرامنگ میکانزم ہے، جو kotlinx.coroutines لائبریری میں نافذ ہے۔ آپریٹنگ سسٹم تھریڈ کے برعکس، کوروٹینز کسی مخصوص تھریڈ سے منسلک نہیں ہوتے: وہ ایک تھریڈ پر رک سکتے ہیں اور دوسرے پر دوبارہ شروع ہو سکتے ہیں۔ ایک ہی تھریڈ کم سے کم اضافی لاگت کے ساتھ ہزاروں کوروٹینز پر سوئچ کر سکتا ہے۔
کوروٹینز Kotlin 1.3 (2018) میں ایک تجرباتی خصوصیت کے طور پر ظاہر ہوئے اور Kotlin 1.5 (2021) میں مستحکم ہو گئے۔ Coroutines async/await کی طرح کال بیک ہیل مسئلہ حل کرتے ہیں، لیکن زیادہ بھرپور API فراہم کرتے ہیں: چینل (Channel)، Flow، Job درجہ بندی میں استثناء ہینڈلنگ اور Android Lifecycle کے ساتھ براہ راست انضمام۔
JetBrains (2025) کے مطابق، ہر کوروٹین تقریباً 100 بائٹ میموری استعمال کرتا ہے جبکہ مقامی تھریڈ 1+ MB استعمال کرتا ہے۔ یہ OutOfMemoryError کے خطرے کے بغیر ایک ایپلیکیشن میں لاکھوں کوروٹینز چلانے کی اجازت دیتا ہے۔ کوروٹینز کی ہلکی پھلکی نوعیت ہی انہیں Android میں غیر متوازنیت کے لیے ترجیحی آلہ بناتی ہے۔
ہر Kotlin کوروٹین Continuation Passing Style (CPS) کے ذریعے ایک اسٹیٹ مشین میں مرتب ہوتا ہے۔ کمپائلر ہر suspend فنکشن میں ایک پوشیدہ Continuation پیرامیٹر شامل کرتا ہے۔ Continuation میں دوبارہ شروع کرنے کا نقطہ اور تمام مقامی متغیرات ہوتے ہیں۔ جب کوئی کوروٹین رکتا ہے، رن ٹائم Continuation محفوظ کرتا ہے، اور جب یہ دوبارہ شروع ہوتا ہے تو اسے Dispatcher پول کے کسی بھی دستیاب تھریڈ پر بحال کرتا ہے۔
suspend ایک Kotlin کلیدی لفظ ہے جو کسی فنکشن کو قابل معطل کے طور پر نشان زد کرتا ہے۔ ایسے فنکشن کو صرف دوسرے suspend فنکشن یا کوروٹین سے ہی کال کیا جا سکتا ہے۔ suspend فنکشن کے اندر، آپ کسی بھی ترتیب میں دوسرے suspend فنکشنز کو کال کر سکتے ہیں، اور ہر کال پوائنٹ ایک ممکنہ معطلی کا نقطہ ہے۔
میکانکس آسان ہے: جب کوئی suspend فنکشن دوسرے suspend فنکشن کو کال کرتا ہے، تو یہ اس نقطہ پر رک جاتا ہے، تھریڈ کو آزاد کرتا ہے۔ کال شدہ فنکشن مکمل ہونے کے بعد، رن ٹائم محفوظ کردہ مقام سے اجراء جاری رکھتا ہے۔ اسے باہمی تعاون سے منسوخی (cooperative cancellation) کہا جاتا ہے — کوئی تھریڈ مسدود نہیں ہوتا۔
اہم: suspend فنکشن بطور ڈیفالٹ غیر متوازن نہیں ہے۔ اگر launch یا async استعمال نہ کیا جائے تو اجراء کا ترتیب سلسلہ وار رہتا ہے۔ suspend صرف فنکشن کو تھریڈ کو مسدود کیے بغیر رکنے اور کوروٹین سیاق و سباق کا حصہ بننے کی اجازت دیتا ہے۔ Continuation Passing Style ایک مرتب کرنے کا ماڈل ہے جہاں ہر suspend فنکشن ایک پوشیدہ Continuation کال بیک وصول کرتا ہے، اور کمپائلر معطلیوں اور دوبارہ شروع کرنے کے انتظام کے لیے ایک اسٹیٹ مشین تیار کرتا ہے۔
CoroutineScope ایک سیاق و سباق ہے جو کوروٹینز کی زندگی کے دور کی وضاحت کرتا ہے۔ تمام کوروٹینز کو دائرہ کار کے اندر شروع کیا جانا چاہیے۔ جب کوئی دائرہ کار منسوخ ہوتا ہے (مثال کے طور پر، Activity ختم ہونے پر)، اس کے تمام ذیلی کوروٹینز خود بخود منسوخ ہو جاتے ہیں۔ یہ پس منظر کے کاموں کے رساو کو روکتا ہے۔ Android Jetpack ہر جزو کے لیے تیار دائرہ کار فراہم کرتا ہے: ViewModel کے لیے viewModelScope اور Activity/Fragment کے لیے lifecycleScope، جو متعلقہ جزو تباہ ہونے پر خود بخود منسوخ ہو جاتے ہیں۔
ساختی ہم وقتی (Structured Concurrency) ایک اصول ہے جو اس بات کی ضمانت دیتا ہے کہ ایک کوروٹین اس وقت تک مکمل نہیں ہوگا جب تک اس کے تمام ذیلی کوروٹینز مکمل نہ ہو جائیں۔ Job کا درجہ بندی ایک درخت بناتی ہے: ایک جڑ کوروٹین ایک والدین job بناتا ہے، بچے بچوں کے jobs بناتے ہیں۔ والدین job کی منسوخی تمام بچوں تک پھیل جاتی ہے۔ Structured Concurrency کوروٹینز اور تھریڈز کے درمیان ایک بنیادی فرق ہے۔
| Scope | کہاں استعمال ہوتا ہے | منسوخی |
|---|---|---|
| GlobalScope | صرف ڈیمن کاموں کے لیے | خود بخود منسوخ نہیں ہوتا |
| viewModelScope | Android ViewModel | ViewModel صاف ہونے پر |
| lifecycleScope | Android Activity/Fragment | lifecycle تباہ ہونے پر |
| coroutineScope | suspend فنکشن کے اندر | والدین job منسوخ ہونے پر |
عام Job ایک ذیلی کوروٹین کے ناکام ہونے پر تمام ہم درجہ افراد کو منسوخ کر دیتا ہے۔ SupervisorJob ایک استثناء ہے: ایک ذیلی کوروٹین میں ناکامی دوسروں کو متاثر نہیں کرتی۔ یہ اس وقت اہم ہے جب متعدد آزاد کام متوازی طور پر انجام دیے جا رہے ہوں اور ان میں سے ایک دوسروں کو منسوخ کیے بغیر کریش ہو سکتا ہے۔
Dispatchers تعین کرتے ہیں کہ کوروٹینز کن تھریڈز پر انجام دی جائیں۔ Dispatchers.Main — مرکزی Android UI تھریڈ۔ Dispatchers.IO — مسدود کرنے والی کارروائیوں (نیٹ ورک، ڈسک) کے لیے ایک پول۔ Dispatchers.Default — CPU گہرے کاموں کے لیے۔ Dispatchers.Unconfined — موجودہ تھریڈ میں شروع ہوتا ہے لیکن اس پر رہنے کی ضمانت نہیں دیتا۔ صحیح Dispatcher کا انتخاب کارکردگی کے لیے اہم ہے: Default پر IO کام کمپیوٹ پول کو مسدود کر دے گا، جبکہ IO پر CPU کام غیر ضروری تھریڈز پیدا کرے گا۔
withContext — کوروٹین کے اندر Dispatcher تبدیل کرنے کے لیے ایک فنکشن۔ مثال کے طور پر، JSON پارس کرنے والا suspend فنکشن حساب کے لیے Dispatchers.Default پر جا سکتا ہے اور UI اپ ڈیٹ کے لیے Dispatchers.Main پر واپس آ سکتا ہے۔ withContext Android ڈویلپمنٹ میں سب سے زیادہ استعمال ہونے والا بلڈر ہے۔
launch — کوروٹین شروع کرتا ہے، Job لوٹاتا ہے، نتیجہ واپس نہیں کرتا (fire-and-forget)۔ async — کوروٹین شروع کرتا ہے، Deferred لوٹاتا ہے جس سے await کے ذریعے نتیجہ حاصل کیا جا سکتا ہے۔ runBlocking — کوروٹین کو انجام دینے کے لیے موجودہ تھریڈ کو مسدود کرتا ہے (صرف ٹیسٹ اور main فنکشنز کے لیے)۔ بلڈر کا انتخاب منظر نامے پر منحصر ہے: launch واقعات اور اپ ڈیٹس کے لیے موزوں ہے، async نتیجہ والے کاموں کے لیے، runBlocking صرف ٹیسٹ یا داخلے کے مقامات کے لیے۔
آئیے تین عملی منظرناموں پر غور کریں: launch کے ساتھ ایک بنیادی کوروٹین، async کے ساتھ متوازی کال، اور SupervisorJob کے ساتھ غلطی کا انتظام۔
viewModelScope.launch ViewModel سیاق و سباق میں کوروٹین شروع کرتا ہے۔ ViewModel صاف ہونے پر کوروٹین خود بخود منسوخ ہو جاتا ہے۔
class ProfileViewModel : ViewModel() {
fun loadUser() {
viewModelScope.launch(Dispatchers.IO) {
val user = api.fetchUser()
withContext(Dispatchers.Main) {
showUser(user)
}
}
}
}
coroutineScope async کے ساتھ تین درخواستیں متوازی طور پر شروع کرتا ہے۔ نتائج .await() کے ذریعے جمع کیے جاتے ہیں۔ اگر کوئی درخواست ناکام ہوتی ہے تو تمام منسوخ ہو جاتی ہیں۔
suspend fun loadDashboard(): Dashboard = coroutineScope {
val user = async { api.fetchUser() }
val posts = async { api.fetchPosts() }
val stats = async { api.fetchStats() }
Dashboard(user.await(), posts.await(), stats.await())
}
SupervisorJob ہر کوروٹین کو آزادانہ طور پر مکمل ہونے دیتا ہے۔ ایک درخواست میں غلطی دوسروں کو منسوخ نہیں کرتی۔
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try { api.fetchUsers() } catch (e: Exception) { log(e) }
}
scope.launch {
try { api.fetchPosts() } catch (e: Exception) { log(e) }
}
تھریڈ آپریٹنگ سسٹم کا ایک ابتدائی عنصر ہے۔ ہر تھریڈ کا اپنا اسٹیک (~1 MB) ہوتا ہے اور اسے بنانے اور سوئچ کرنے کے لیے سسٹم کال کی ضرورت ہوتی ہے۔ کوروٹینز زبان کا ایک ابتدائی عنصر ہے، OS سے منسلک نہیں۔ وہ حالت محفوظ کرنے کے لیے Continuation استعمال کرتے ہیں اور سسٹم کال کے بغیر رن ٹائم سطح پر سوئچ کرتے ہیں۔
Google (2025) کے مطابق، تھریڈ کے بجائے کوروٹین استعمال کرنے سے Android ایپلیکیشنز میں پس منظر کے کاموں کے لیے میموری کی کھپت 90-95% کم ہو جاتی ہے۔ تمام جدید Android لائبریریاں (Retrofit, Room, WorkManager) suspend فنکشنز کے ذریعے بلٹ ان کوروٹین سپورٹ رکھتی ہیں۔ Ktor (JetBrains کا HTTP کلائنٹ فریم ورک) بھی مکمل طور پر کوروٹینز پر بنایا گیا ہے، جو کال بیک API کے بغیر ہر درخواست کے لیے suspend فنکشن فراہم کرتا ہے۔ Room DAO میں suspend فنکشنز کے ذریعے کوروٹینز کو سپورٹ کرتا ہے، جس سے مرکزی تھریڈ کو مسدود کیے بغیر ڈیٹا بیس کے سوالات انجام دیے جا سکتے ہیں۔
تھریڈ JNI کے ذریعے مقامی کوڈ، طویل عرصے تک چلنے والی CPU گہری مسدود کرنے والی کالز (ویڈیو رینڈرنگ، سمیلیشنز) اور C لائبریریوں کے ساتھ انضمام کے لیے ضروری رہتے ہیں۔ باقی سب کے لیے — کوروٹینز۔
اکثر پوچھے گئے سوالات
کوروٹین کام کی ایک معطل اکائی ہے جو موجودہ تھریڈ پر انجام دی جاتی ہے۔ تھریڈ اپنے اسٹیک کے ساتھ ایک سسٹم وسیلہ ہے۔ کوروٹینز تھریڈ سے ہزاروں گنا ہلکے ہیں اور معطل ہونے پر وسائل کو مسدود نہیں کرتے۔
Dispatchers.IO مسدود کرنے والی I/O کارروائیوں (نیٹ ورک، فائلیں) کے لیے ڈیزائن کیا گیا ہے اور ضرورت پڑنے پر نئے تھریڈ بنا سکتا ہے۔ Dispatchers.Default CPU گہرے حسابات کے لیے ایک مقررہ سائز کا پول (CPU کورز کی تعداد) رکھتا ہے۔
Job.cancel() کوروٹین اور اس کے تمام بچوں کو منسوخ کرتا ہے۔ کوروٹین کے اندر منسوخی چیک کرنے کے لیے، ensureActive() استعمال کریں — یہ CancellationException پھینکتا ہے اگر کوروٹین منسوخ کر دیا گیا ہو۔
ہاں — kotlinx-coroutines-rx3 لائبریری کے ذریعے۔ یہ Observable/Single کو suspend فنکشنز میں تبدیل کرنے اور flowable کے ذریعے واپس لانے کے لیے awaitSingle، awaitFirst اور دیگر فنکشنز فراہم کرتی ہے۔
Flow ایک ٹھنڈا غیر متوازن ڈیٹا سٹریم ہے، جو کوروٹینز میں RxJava Observable کے برابر ہے۔ Flow ترتیب وار اقدار خارج کرتا ہے اور استثناء یا کامیابی کے ساتھ مکمل ہوتا ہے۔ یہ map، filter، catch اور دیگر آپریٹرز کو سپورٹ کرتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں