DEV Community

Papon Ahasan
Papon Ahasan

Posted on • Edited on

Process, Thread, Multi-threading, Concurrency

✅ Process মানে হচ্ছে একটা running program যেটার নিজস্ব memory space থাকে, কিছু data আর resource ধারণ করে, এবং নির্দিষ্ট একটা কাজ করে।

🧠 উদাহরণ:
আমি যদি একসাথে Chrome Browser, VS Code আর Postman চালাই—এগুলো প্রত্যেকটা হচ্ছে আলাদা আলাদা process।

✅ Thread মানে একটা process এর ভেতরে ছোট কাজের unit, যেগুলো একই মেমোরি শেয়ার করে একসাথে আলাদা কাজ করতে পারে।

🧠 উদাহরণ:
Chrome browser-এর প্রতিটা ট্যাব, UI interaction, ভিডিও প্লে—এগুলো প্রত্যেকটা আলাদা thread দিয়ে পরিচালিত হতে পারে।

📌 মোটাদাগে বললে:
Process যদি হয় একটা অ্যাপ, Thread হচ্ছে ঐ অ্যাপের ভেতরের একাধিক রানিং টাস্ক।

✅ Multithreading মানে:
একটা প্রসেস যখন একাধিক থ্রেড তৈরি করে, এবং সেই থ্রেডগুলো একই সময়ে আলাদা কাজ করে।

🧠 উদাহরণ:
একটা অ্যাপে একদিকে ডাটা লোড হচ্ছে, অন্যদিকে ইউজারের ইন্টারঅ্যাকশন হ্যান্ডেল হচ্ছে — এসব একাধিক থ্রেডে হয়ে থাকে।

✅ Concurrency মানে:
একই সময়ে একাধিক কাজ handle করা। যদিও সব কাজ একসাথে (parallel) না হয়ে সময় ভাগ করে চলে।

🧠 উদাহরণ:
আমি রান্না করছি, মাঝে মাঝে ভাত নেড়ে দিচ্ছি, আবার মাঝে মাঝে ডাল ও চেক করছি। এইযে একই সময়ে দুইটা কাজ সামলানো সময় ভাগ করে করে—এটাই concurrency।

সর্বসাকুল্যে বললে,
Process হচ্ছে সম্পূর্ণ আলাদা প্রোগ্রাম, নিজের মেমোরি সহ।
Thread হলো প্রসেসের ভেতরে ছোট ছোট কাজের ইউনিট।
Multithreading হচ্ছে একই প্রসেসে একাধিক থ্রেড একসাথে চালানো, আর
Concurrency হলো একইসাথে একাধিক কাজ সামলানো (parallel না হলেও)

About Concurrency

The following code block does not execute async { ... } blocks one by one. Instead, it executes all of them concurrently(start in parallel, not in sequence): Achieving concurrency using multiple threads.

val results = coroutineScope {
    listOf(
        async { syncWrapper("Keys") { getKeys() } },
        async { syncWrapper("Advertisement") { getAdvertisement() } },
        async { syncWrapper("Company") { getCompany() } },
        async { syncWrapper("Generic") { getGeneric() } },
    ).awaitAll()
}
Enter fullscreen mode Exit fullscreen mode
  • Each async { ... } block starts running immediately and concurrently within the same coroutineScope.

  • awaitAll() suspends the current coroutine until all async jobs are finished, and returns their results in a list.

🔥 Benefits of Concurrent Execution (async {} in coroutineScope)

  • Faster overall time: All sync operations run at the same time, so total duration ≈ longest task, not sum of all tasks.

  • Efficient use of resources: If your sync logic involves network or disk I/O, concurrent coroutines can improve throughput.

  • Independent tasks: Like If getKeys(), getAdvertisement(), etc. are not dependent on each other, there’s no reason to wait unnecessarily.

Example: If each task takes 2 seconds:

  • Sequential = 4 tasks × 2s = 8 seconds.
  • Concurrent = all in parallel = around 2–3 seconds total.

When to prefer Sequential Execution

You may want to sync one after another only if:

  • Tasks depend on each other (e.g., you must sync keys before ads).

  • You want to rate-limit or throttle requests to avoid hitting a server too hard.

  • You want simple, predictable error handling — easier in sequence sometimes.

💡 Best Practice (Hybrid):

You can use concurrent groups for independent tasks and sequential for dependent ones:

val results = coroutineScope {
    val firstBatch = listOf(
        async { syncWrapper("Keys") { getKeys() } },
        async { syncWrapper("Company") { getCompany() } }
    ).awaitAll()

    val secondBatch = listOf(
        async { syncWrapper("Advertisement") { getAdvertisement() } },
        async { syncWrapper("Generic") { getGeneric() } }
    ).awaitAll()

    firstBatch + secondBatch
}
Enter fullscreen mode Exit fullscreen mode
val results = coroutineScope {
    // Run independent tasks concurrently
    val firstBatch = listOf(
        async { syncWrapper("Keys") { getKeys() } },
        async { syncWrapper("Advertisement") { getAdvertisement() } }
    ).awaitAll()

    // Then run dependent tasks in sequence
    val secondBatch = listOf(
        syncWrapper("Company") { getCompany() },
        syncWrapper("Generic") { getGeneric() }, // depends on Company
        syncWrapper("Product") { getProducts() } // depends on Generic
    )

    firstBatch + secondBatch
}
Enter fullscreen mode Exit fullscreen mode

❗ Potential Problems with Concurrent Sync When Data Depends on Each Other:

Example scenario:

  • getCompany() must run before getGeneric() because Generic has a company_id foreign key.

  • If getGeneric() runs before or at the same time as getCompany(), the database may:

    • 🔥 Throw a foreign key constraint error, or
    • Insert incomplete or orphaned records.

So, 🔁 Sequential Execution

Runs one by one, even for independent tasks, like this: ⏱ Slower overall, because independent tasks wait unnecessarily. ❌ Full Sequential - 5 sec

Keys  Advertisement  Company  Generic  Product  ...
Enter fullscreen mode Exit fullscreen mode

⚡ Mixed (Concurrent + Sequential):
✅ Runs independent tasks together, and only waits where needed:
✅ Faster overall, because you only block where necessary.
✅ Mixed ~3 sec (Keys + Ads run together)

[Keys, Advertisement]  Company  Generic  Product
Enter fullscreen mode Exit fullscreen mode

1. What is the difference between concurrency and multithreading
Answer:

Concurrency is a concept: managing multiple tasks at once.

Multithreading is a technique: achieving concurrency using multiple threads.

2. In Android, why shouldn’t we do heavy tasks on the main thread?

Answer:
The main thread handles UI updates. Doing heavy work (like network/database) blocks it and causes ANR (App Not Responding) errors.

3. What are the advantages of using multiple threads in an app?
Answer:

  • Better responsiveness (UI thread not blocked)
  • Faster performance (I/O or network in background threads)
  • Efficient resource usage

Top comments (0)