Dispatchers — মূল ধারণা, ডিসপ্যাচারের প্রকার এবং কীভাবে কাজ করে

লেখক: IT Sectr প্রকাশিত: 2026-06-22 পড়ার সময়: 9 মিনিট

Dispatchers Kotlin Coroutines-এ CoroutineContext-এর উপাদান যা coroutines সম্পাদনের জন্য থ্রেড নির্ধারণ করে: Main (UI থ্রেড), IO (নেটওয়ার্ক এবং ডিস্ক), Default (CPU-নিবিড় কাজ) এবং Unconfined (বর্তমান থ্রেড)। প্রতিটি ডিসপ্যাচার একটি বিশেষায়িত থ্রেড পুল পরিচালনা করে যা নির্দিষ্ট ধরণের কাজের জন্য অপ্টিমাইজ করা হয়েছে। JetBrains গাইড, 2024 অনুসারে, সঠিক ডিসপ্যাচার নির্বাচন করা অ্যাপ্লিকেশনের কর্মক্ষমতা এবং স্থিতিশীলতার জন্য গুরুত্বপূর্ণ।

মূল পয়েন্ট

  • Dispatchers — পূর্বনির্ধারিত coroutine ডিসপ্যাচার যা থ্রেড জুড়ে কাজ বিতরণ পরিচালনা করে
  • Dispatchers.Main — Android UI থ্রেড, ইন্টারফেস আপডেট এবং View নিয়ে কাজ করার জন্য
  • Dispatchers.IO — নেটওয়ার্ক অনুরোধ, ফাইল রিড/রাইট এবং DB-র জন্য পুল (64 থ্রেড পর্যন্ত)
  • Dispatchers.Default — প্রসেসর কোরের সংখ্যার উপর ভিত্তি করে CPU-নিবিড় কাজের জন্য পুল
  • Dispatchers.Unconfined — বর্তমান থ্রেড উত্তরাধিকার সূত্রে প্রাপ্ত হয়, সুইচিং ছাড়াই

Dispatchers কী?

Dispatchers হল CoroutineDispatcher ইন্টারফেসের বাস্তবায়ন, যা CoroutineContext-এর উপাদান। তারা নির্ধারণ করে কোন থ্রেড বা থ্রেড পুলে coroutine সম্পাদিত হবে। launch বা async-এর মাধ্যমে coroutine তৈরি করার সময়, ডিসপ্যাচারটি প্রথম প্যারামিটার হিসাবে পাস করা যেতে পারে: launch(Dispatchers.IO) { ... }। যদি কোনো ডিসপ্যাচার নির্দিষ্ট না করা হয়, তবে এটি বাইরের CoroutineScope থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়।

Kotlin চারটি অন্তর্নির্মিত ডিসপ্যাচার প্রদান করে: Main, IO, Default, Unconfined। প্রতিটি ডিসপ্যাচার নির্দিষ্ট ধরণের অপারেশনের জন্য অপ্টিমাইজ করা নিজস্ব থ্রেড পুল ব্যবহার করে। সঠিক ডিসপ্যাচার নির্বাচন অ্যাপ্লিকেশনের কর্মক্ষমতা নির্ধারণ করে: ভুল পছন্দ UI ল্যাগ, নিষ্ক্রিয় CPU কোর বা অদক্ষ থ্রেড ব্যবহারের দিকে নিয়ে যায়।

ডিসপ্যাচারথ্রেড পুলসর্বোচ্চ থ্রেডব্যবহার
Dispatchers.Mainএক (UI)1UI আপডেট, LiveData, View
Dispatchers.IOIO পুল64 (limitedParallelism)নেটওয়ার্ক, ফাইল, DB
Dispatchers.DefaultCPU পুলN কোরসাজানো, পার্সিং, গণনা
Dispatchers.Unconfinedবর্তমান থ্রেডপ্রযোজ্য নয়মধ্যবর্তী অপারেশন, পরীক্ষা

Dispatchers.Main: UI থ্রেড

Dispatchers.Main হল ডিসপ্যাচার যা Android প্রধান থ্রেডে coroutines সম্পাদন করে। এটি UI-সম্পর্কিত অপারেশনের জন্য ডিজাইন করা হয়েছে: TextView আপডেট করা, notifyDataSetChanged কল করা, LiveData এবং StateFlow নিয়ে কাজ করা। Android-এ, এই ডিসপ্যাচারটি Handler (Looper.getMainLooper()) এর মাধ্যমে বাস্তবায়িত হয়।

kotlin
// Correct switch to Main for UI updates
viewModelScope.launch(Dispatchers.IO) {
    val data = repository.fetchData()
    withContext(Dispatchers.Main) {
        _uiState.value = data
    }
}

যদি একটি coroutine ইতিমধ্যেই Main ডিসপ্যাচারে থাকে, তবে অতিরিক্ত withContext(Dispatchers.Main) কোনো ওভারহেড তৈরি করে না — ডিসপ্যাচার বর্তমান থ্রেড পরীক্ষা করে এবং সুইচ এড়িয়ে যায়। withContext হল ডিসপ্যাচারগুলির মধ্যে সুইচ করার পছন্দের উপায়।

Dispatchers.IO: নেটওয়ার্ক এবং ডিস্ক অপারেশন

Dispatchers.IO হল একটি ডিসপ্যাচার যা I/O অপারেশনের জন্য অপ্টিমাইজ করা: HTTP অনুরোধ (Ktor, OkHttp), ফাইল পড়া এবং লেখা, Room বা SQLDelight নিয়ে কাজ করা। এটি ডিফল্টভাবে 64 থ্রেড-এর একটি পুল ব্যবহার করে, যা লোডের অধীনে স্কেলযোগ্য। প্রতিটি নতুন I/O অনুরোধ সীমায় পৌঁছানো পর্যন্ত একটি অতিরিক্ত থ্রেড তৈরি করতে পারে।

সমান্তরালতা সীমিত করা

সমন্বিত I/O অপারেশনের সংখ্যা নিয়ন্ত্রণ করতে, limitedParallelism() ব্যবহার করুন। এই ফাংশনটি সমান্তরাল থ্রেডের সংখ্যার সীমা সহ একটি নতুন ডিসপ্যাচার তৈরি করে, যা বাল্ক অপারেশনের সময় পুল শেষ হয়ে যাওয়া প্রতিরোধ করে।

kotlin
val limitedIo = Dispatchers.IO.limitedParallelism(4)

// Load 100 files with limit of 4 concurrent operations
coroutineScope {
    val files = (1..100).map { index ->
        async(limitedIo) {
            downloadFile("file_$index")
        }
    }
    files.awaitAll()
}

সমস্ত অপারেশনের জন্য IO ডিসপ্যাচার ব্যবহার করুন যেখানে coroutine অপেক্ষায় সময় কাটায় (I/O-bound)। IO ডিসপ্যাচারে CPU-নিবিড় কাজ অদক্ষ — তারা I/O-র জন্য নির্ধারিত থ্রেড দখল করে, সিস্টেমের থ্রুপুট হ্রাস করে।

Dispatchers.Default: CPU-নিবিড় কাজ

Dispatchers.Default হল কম্পিউটেশন অপারেশনের জন্য ডিসপ্যাচার যা প্রসেসর লোড করে: সাজানো, ফিল্টারিং, JSON পার্সিং (Moshi, Kotlinx Serialization), ইমেজ প্রসেসিং, গণনা। পুলের আকার প্রসেসর কোরের সংখ্যার সমান (কিন্তু 2-এর কম নয়)। এটি প্রসঙ্গ সুইচিং ছাড়াই সর্বাধিক CPU ব্যবহার নিশ্চিত করে।

kotlin
suspend fun processData(input: List<RawRecord>): List<ProcessedRecord> {
    return withContext(Dispatchers.Default) {
        input
            .parallelStream()
            .map { transform(it) }
            .toList()
    }
}

I/O অপারেশনের জন্য Dispatchers.Default ব্যবহার করবেন না — এটি CPU পুলের থ্রেড ব্লক করবে যা কম্পিউটেশনাল কাজ প্রক্রিয়া করতে পারত। IO এবং Default আলাদা করা সিস্টেম সংস্থানের অনুকূল ব্যবহার নিশ্চিত করে: IO থ্রেড I/O-র জন্য অপেক্ষা করে, CPU থ্রেড ক্রমাগত গণনার সাথে ব্যস্ত থাকে।

Dispatchers.Unconfined: বর্তমান থ্রেড

Dispatchers.Unconfined হল একটি বিশেষ ডিসপ্যাচার যা coroutine-কে কোনো পুলের সাথে আবদ্ধ করে না। Coroutine যে থ্রেডে launch/async কল করা হয়েছিল সেখানে সম্পাদন শুরু করে এবং স্থগিত করার পরে যে থ্রেড resume কল করেছে সেখানে পুনরায় শুরু হয়। এই আচরণ মধ্যবর্তী অপারেশনের জন্য উপযুক্ত যার নির্দিষ্ট প্রসঙ্গের প্রয়োজন নেই।

kotlin
fun main() = runBlocking {
    launch(Dispatchers.Unconfined) {
        println("Before delay: ${Thread.currentThread().getName()}")
        delay(500L)
        println("After delay: ${Thread.currentThread().getName()}")
    }
}

প্রোডাকশন কোডে, Dispatchers.Unconfined খুব কমই ব্যবহৃত হয়। প্রধান ব্যবহারের ক্ষেত্রে: অন্য ডিসপ্যাচারে ডেটা পাস করার আগে হালকা রূপান্তর এবং পরীক্ষা। প্রোডাকশন ওয়ার্কলোডের জন্য, স্পষ্ট ডিসপ্যাচার ব্যবহার করুন — Unconfined অপ্রত্যাশিত কারণ সম্পাদন থ্রেড resume বাস্তবায়নের উপর নির্ভর করে।

কীভাবে ডিসপ্যাচার নির্বাচন করবেন

ডিসপ্যাচার নির্বাচন কাজের ধরণের উপর নির্ভর করে: UI অপারেশন → Main, I/O-bound → IO, CPU-bound → Default, মধ্যবর্তী → scope থেকে উত্তরাধিকার। Android-এর জন্য, coroutine সেই ডিসপ্যাচারে লঞ্চ করার পরামর্শ দেওয়া হয় যেখানে মূল কাজ সম্পাদিত হয়, এবং UI আপডেট করার আগে withContext-এর মাধ্যমে Main-এ সুইচ করুন।

  • Main ডিসপ্যাচারে I/O অপারেশন চালাবেন না — এটি UI ব্লক করে
  • IO ডিসপ্যাচারে CPU-নিবিড় কাজ চালাবেন না — এটি IO পুলের থ্রেড অদক্ষভাবে ব্যবহার করে
  • বাল্ক I/O অপারেশনের সময় সমবর্তিতা নিয়ন্ত্রণ করতে limitedParallelism ব্যবহার করুন
  • নতুন scope তৈরি না করে withContext ব্যবহার করে ডিসপ্যাচার পরিবর্তন করুন
  • coroutine-এর নির্দিষ্ট পুলের প্রয়োজন না হলে scope থেকে ডিসপ্যাচার উত্তরাধিকার সূত্রে নিন

জটিল পরিস্থিতির জন্য, + অপারেটর ব্যবহার করে ডিসপ্যাচার একত্রিত করুন: Dispatchers.IO + SupervisorJob() + CoroutineExceptionHandler. এটি নির্দিষ্ট ডিসপ্যাচার, ত্রুটি হ্যান্ডলিং এবং বিচ্ছিন্ন Job শ্রেণিবিন্যাস সহ একটি CoroutineContext তৈরি করে।

সচরাচর জিজ্ঞাসিত প্রশ্ন

Dispatchers.IO এবং Dispatchers.Default-এর মধ্যে পার্থক্য কী?

Dispatchers.IO I/O-bound অপারেশনের (I/O-র জন্য অপেক্ষা) জন্য 64 থ্রেড পর্যন্ত একটি পুল ব্যবহার করে, যখন Dispatchers.Default কম্পিউটেশনাল কাজের জন্য CPU কোরের সংখ্যার উপর ভিত্তি করে একটি পুল ব্যবহার করে। যখন থ্রেড দুষ্প্রাপ্য হয়, উভয় পুল একে অপরের সাথে থ্রেড ভাগ করতে পারে।

আমি কি Kotlin Coroutines-এ নিজস্ব ডিসপ্যাচার তৈরি করতে পারি?

হ্যাঁ, একক-থ্রেডের জন্য newSingleThreadContext() বা ফিক্সড পুলের জন্য newFixedThreadPoolContext() ব্যবহার করুন। প্রোডাকশনের জন্য, বিদ্যমান ডিসপ্যাচারের উপর ভিত্তি করে limitedParallelism() ব্যবহার করুন — এটি নতুন পুল তৈরি করার চেয়ে বেশি কার্যকর।

ব্যাকগ্রাউন্ড থ্রেড থেকে Dispatchers.Main কল করলে কী হয়?

যদি Dispatchers.Main উপলব্ধ না থাকে (যেমন, JUnit পরীক্ষা বা ব্যাকগ্রাউন্ড সার্ভিসে), তাহলে একটি IllegalStateException নিক্ষেপ করা হয়। পরীক্ষার জন্য TestCoroutineDispatcher এবং ব্যাকগ্রাউন্ড সার্ভিসের জন্য Dispatchers.IO বা Default ব্যবহার করুন।

কীভাবে সমান্তরাল I/O অপারেশনের সংখ্যা সীমিত করবেন?

Dispatchers.IO.limitedParallelism(N) ব্যবহার করুন, যেখানে N সমান্তরাল থ্রেডের সর্বোচ্চ সংখ্যা। এটি বাল্ক অনুরোধের সময় পুল শেষ হয়ে যাওয়া প্রতিরোধ করে এবং নিয়ন্ত্রিত সমান্তরালতা প্রদান করে।

কখন Dispatchers.Unconfined ব্যবহার করবেন?

Dispatchers.Unconfined মধ্যবর্তী অপারেশনের জন্য উপযুক্ত: অন্য ডিসপ্যাচারে পাস করার আগে হালকা ডেটা রূপান্তর, পরীক্ষার পরিস্থিতি। প্রোডাকশন Android কোডে, স্থগিত করার পরে অনির্ধারিত সম্পাদন থ্রেডের কারণে এটি সুপারিশ করা হয় না।

সারাংশ

  • Dispatchers — CoroutineContext-এর উপাদান যা coroutine সম্পাদন থ্রেড নির্ধারণ করে
  • Dispatchers.Main — Android UI অপারেশনের জন্য, একটি প্রধান থ্রেড
  • Dispatchers.IO — নেটওয়ার্ক এবং ডিস্ক অপারেশনের জন্য, 64 থ্রেড পর্যন্ত পুল
  • Dispatchers.Default — CPU-নিবিড় গণনার জন্য, কোরের সংখ্যার উপর ভিত্তি করে পুল
  • Dispatchers.Unconfined — থ্রেড বাইন্ডিং ছাড়া, মধ্যবর্তী অপারেশনের জন্য
  • withContext — coroutine-এর ভিতরে ডিসপ্যাচারগুলির মধ্যে সুইচ করার প্রধান প্রক্রিয়া
  • ভুল ডিসপ্যাচার নির্বাচন করলে UI ল্যাগ বা অদক্ষ সংস্থান ব্যবহার হয়

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন