Android Multithreading Kotlin Samples

Android Kotlin multithreading examples including thread creation, synchronization with locks, and thread pool usage

Key Facts

Category
Kotlin
Items
3
Format Families
sample

Sample Overview

Android Kotlin multithreading examples including thread creation, synchronization with locks, and thread pool usage This sample set belongs to Kotlin and can be used to test related workflows inside Elysia Tools.

💻 Thread Creation kotlin

🟢 simple ⭐⭐⭐

Create and start threads using various methods including Thread class, Runnable, and Kotlin Coroutines

⏱️ 25 min 🏷️ kotlin, android, multithreading, coroutines
Prerequisites: Basic Kotlin knowledge, Understanding of concurrency
// Android Kotlin Thread Creation Examples
// Using Thread, Runnable, and Coroutines

import android.os.Handler
import android.os.Looper
import kotlinx.coroutines.*

// 1. Basic Thread Creation
class BasicThreadCreation {

    // Create thread using Thread class
    fun createBasicThread() {
        val thread = Thread {
            println("Thread running: ${Thread.currentThread().name}")
            // Perform background work
            Thread.sleep(1000)
            println("Thread completed")
        }

        thread.start()
    }

    // Create thread with custom name
    fun createNamedThread(name: String) {
        val thread = Thread({
            println("Named thread: ${Thread.currentThread().name}")
            // Perform work
        }, name)

        thread.start()
    }

    // Create thread using Runnable
    fun createThreadWithRunnable() {
        val runnable = Runnable {
            println("Runnable thread: ${Thread.currentThread().name}")
        }

        val thread = Thread(runnable)
        thread.start()
    }

    // Create thread with lambda
    fun createThreadWithLambda() {
        Thread {
            println("Lambda thread: ${Thread.currentThread().name}")
            performWork()
        }.start()
    }

    private fun performWork() {
        // Simulate work
        Thread.sleep(500)
        println("Work completed")
    }
}

// 2. Kotlin Coroutines (Recommended for Android)
class CoroutineExamples {

    private val scope = CoroutineScope(Dispatchers.Default + Job())

    // Launch a coroutine
    fun launchCoroutine() {
        scope.launch {
            println("Coroutine running on: ${Thread.currentThread().name}")
            delay(1000)
            println("Coroutine completed")
        }
    }

    // Launch coroutine on IO dispatcher
    fun launchIOCoroutine() {
        scope.launch(Dispatchers.IO) {
            println("IO coroutine on: ${Thread.currentThread().name}")
            // Perform IO operations
        }
    }

    // Launch coroutine on Main thread
    fun launchMainCoroutine() {
        scope.launch(Dispatchers.Main) {
            println("Main coroutine on: ${Thread.currentThread().name}")
            // Update UI
        }
    }

    // Async coroutine with return value
    suspend fun asyncCoroutine(): Int = withContext(Dispatchers.Default) {
        println("Async coroutine on: ${Thread.currentThread().name}")
        delay(1000)
        42
    }

    // Run blocking coroutine
    fun runBlockingCoroutine() {
        runBlocking {
            println("Blocking coroutine on: ${Thread.currentThread().name}")
            launch {
                delay(500)
                println("Child coroutine completed")
            }
            println("Parent coroutine continuing")
        }
    }

    // Cancel scope
    fun cancelAll() {
        scope.cancel()
    }
}

// 3. Advanced Thread Operations
class AdvancedThreadOperations {

    // Thread with exception handling
    fun createThreadWithExceptionHandling() {
        val thread = Thread {
            try {
                println("Thread working...")
                // Simulate error
                throw RuntimeException("Thread error!")
            } catch (e: Exception) {
                println("Caught exception in thread: ${e.message}")
            }
        }

        thread.setUncaughtExceptionHandler { t, e ->
            println("Uncaught exception in ${t.name}: ${e.message}")
        }

        thread.start()
    }

    // Thread with priority
    fun createThreadWithPriority() {
        val thread = Thread {
            println("High priority thread running")
        }.apply {
            priority = Thread.MAX_PRIORITY
        }

        thread.start()
    }

    // Daemon thread
    fun createDaemonThread() {
        val thread = Thread {
            var count = 0
            while (true) {
                println("Daemon thread: $count")
                Thread.sleep(1000)
                count++
            }
        }.apply {
            isDaemon = true
        }

        thread.start()

        // Main thread exits, daemon thread terminates
    }

    // Thread sleep and join
    fun createThreadWithJoin() {
        val thread1 = Thread {
            println("Thread 1 starting")
            Thread.sleep(1000)
            println("Thread 1 completed")
        }

        val thread2 = Thread {
            println("Thread 2 starting")
            Thread.sleep(500)
            println("Thread 2 completed")
        }

        thread1.start()
        thread2.start()

        // Wait for both threads to complete
        thread1.join()
        thread2.join()

        println("All threads completed")
    }
}

// 4. Handler and Looper (Android Specific)
class HandlerLooperExamples {

    private val handler = Handler(Looper.getMainLooper())

    // Post runnable to main thread
    fun postToMainThread() {
        Thread {
            println("Background thread: ${Thread.currentThread().name}")

            // Post result to main thread
            handler.post {
                println("Main thread: ${Thread.currentThread().name}")
                // Update UI
            }
        }.start()
    }

    // Post delayed
    fun postDelayed() {
        handler.postDelayed({
            println("Delayed execution on main thread")
        }, 2000) // 2 seconds delay
    }

    // Post at front of queue
    fun postAtFrontOfQueue() {
        handler.postAtFrontOfQueue {
            println("Execute immediately on main thread")
        }
    }

    // Remove callbacks
    fun removeCallbacks() {
        val runnable = Runnable {
            println("This won't execute")
        }

        handler.post(runnable)
        handler.removeCallbacks(runnable)
    }
}

// 5. Thread Communication
class ThreadCommunication {

    private var sharedData: String = ""

    // Wait and notify
    fun waitNotifyExample() {
        val lock = Object()

        val producerThread = Thread {
            synchronized(lock) {
                println("Producer: Producing data...")
                Thread.sleep(1000)
                sharedData = "Hello from producer"
                println("Producer: Data ready, notifying...")
                lock.notifyAll()
            }
        }

        val consumerThread = Thread {
            synchronized(lock) {
                println("Consumer: Waiting for data...")
                while (sharedData.isEmpty()) {
                    lock.wait()
                }
                println("Consumer: Received: $sharedData")
            }
        }

        consumerThread.start()
        producerThread.start()
    }
}

// 6. Coroutine Context and Scope
class CoroutineContextExamples {

    // Using viewModelScope (requires ViewModel)
    // This is a simulation
    fun viewModelScopeExample() {
        // In a real ViewModel:
        // viewModelScope.launch {
        //     // Work that is cancelled when ViewModel is cleared
        // }

        // Simulation with custom scope
        val customScope = CoroutineScope(Dispatchers.Default)

        customScope.launch {
            println("Custom scope coroutine")
        }
    }

    // Using lifecycleScope (requires LifecycleOwner)
    // This is a simulation
    fun lifecycleScopeExample() {
        // In a Fragment or Activity:
        // lifecycleScope.launch {
        //     // Work that is cancelled when Lifecycle is destroyed
        // }
    }

    // Supervisor job
    fun supervisorJobExample() {
        val supervisor = SupervisorJob()
        val scope = CoroutineScope(Dispatchers.Default + supervisor)

        scope.launch {
            throw RuntimeException("Child 1 failed")
        }

        scope.launch {
            delay(1000)
            println("Child 2 completed")
        }

        // Child 2 continues even though Child 1 failed
    }

    // Coroutine context switching
    suspend fun contextSwitchingExample() {
        withContext(Dispatchers.IO) {
            println("IO work: ${Thread.currentThread().name}")
        }

        withContext(Dispatchers.Main) {
            println("Main work: ${Thread.currentThread().name}")
        }

        withContext(Dispatchers.Default) {
            println("CPU work: ${Thread.currentThread().name}")
        }
    }
}

// 7. Thread Local Storage
class ThreadLocalStorageExample {

    private val threadLocal = ThreadLocal<String>()

    fun threadLocalDemo() {
        val thread1 = Thread {
            threadLocal.set("Value from Thread 1")
            println("Thread 1: ${threadLocal.get()}")
        }

        val thread2 = Thread {
            threadLocal.set("Value from Thread 2")
            println("Thread 2: ${threadLocal.get()}")
        }

        thread1.start()
        thread2.start()

        thread1.join()
        thread2.join()

        println("Main thread: ${threadLocal.get()}")
    }
}

// Main demonstration
fun demonstrateThreadCreation() {
    println("=== Android Kotlin Thread Creation Examples ===\n")

    // 1. Basic thread creation
    println("--- 1. Basic Thread Creation ---")
    val basicThread = BasicThreadCreation()
    basicThread.createBasicThread()
    basicThread.createNamedThread("MyCustomThread")

    // 2. Coroutines (recommended)
    println("\n--- 2. Kotlin Coroutines ---")
    val coroutineExamples = CoroutineExamples()
    coroutineExamples.launchCoroutine()

    // 3. Advanced operations
    println("\n--- 3. Advanced Thread Operations ---")
    val advancedOps = AdvancedThreadOperations()
    advancedOps.createThreadWithJoin()

    // 4. Handler and Looper
    println("\n--- 4. Handler and Looper ---")
    val handlerExamples = HandlerLooperExamples()
    handlerExamples.postToMainThread()

    // 5. Thread communication
    println("\n--- 5. Thread Communication ---")
    val communication = ThreadCommunication()
    communication.waitNotifyExample()

    println("\n=== All Thread Creation Examples Completed ===")
}

💻 Thread Synchronization kotlin

🟡 intermediate ⭐⭐⭐⭐

Synchronize threads using locks, semaphores, and other synchronization mechanisms to protect shared resources

⏱️ 35 min 🏷️ kotlin, android, multithreading, synchronization
Prerequisites: Intermediate Kotlin, Understanding of concurrency
// Android Kotlin Thread Synchronization Examples
// Using locks, semaphores, and synchronization mechanisms

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
import java.util.concurrent.*
import java.util.concurrent.atomic.*
import java.util.concurrent.locks.*

// 1. Synchronized Block
class SynchronizedBlockExample {
    private var counter = 0

    // Using synchronized block
    fun incrementCounter() {
        synchronized(this) {
            counter++
            println("Counter: $counter (Thread: ${Thread.currentThread().name})")
        }
    }

    // Synchronized method
    @Synchronized
    fun decrementCounter() {
        counter--
        println("Counter: $counter (Thread: ${Thread.currentThread().name})")
    }

    fun getCounter(): Int {
        synchronized(this) {
            return counter
        }
    }
}

// 2. ReentrantLock
class ReentrantLockExample {
    private val lock = ReentrantLock()
    private var sharedResource = 0

    fun performTask() {
        lock.lock()
        try {
            println("Lock acquired by ${Thread.currentThread().name}")
            // Critical section
            sharedResource++
            Thread.sleep(100)
            println("Shared resource: $sharedResource")
        } finally {
            lock.unlock()
            println("Lock released by ${Thread.currentThread().name}")
        }
    }

    fun tryLockExample() {
        if (lock.tryLock(1, TimeUnit.SECONDS)) {
            try {
                println("TryLock succeeded")
                // Perform work
            } finally {
                lock.unlock()
            }
        } else {
            println("Could not acquire lock")
        }
    }

    // ReadWriteLock for multiple readers
    private val readWriteLock = ReentrantReadWriteLock()
    private var data = "Initial Data"

    fun readData(): String {
        readWriteLock.readLock().lock()
        try {
            println("Reading: $data")
            return data
        } finally {
            readWriteLock.readLock().unlock()
        }
    }

    fun writeData(newValue: String) {
        readWriteLock.writeLock().lock()
        try {
            println("Writing: $newValue")
            data = newValue
        } finally {
            readWriteLock.writeLock().unlock()
        }
    }
}

// 3. Semaphore
class SemaphoreExample {
    private val semaphore = Semaphore(3) // Allow 3 concurrent accesses

    fun accessResource(id: Int) {
        try {
            semaphore.acquire()
            println("Resource $id acquired by ${Thread.currentThread().name}")

            // Simulate work
            Thread.sleep(1000)
            println("Resource $id released")
        } catch (e: InterruptedException) {
            println("Interrupted: ${e.message}")
        } finally {
            semaphore.release()
        }
    }

    fun tryAcquireExample(id: Int) {
        if (semaphore.tryAcquire()) {
            try {
                println("Resource $id accessed immediately")
                Thread.sleep(500)
            } finally {
                semaphore.release()
            }
        } else {
            println("Resource $id not available")
        }
    }
}

// 4. Atomic Variables
class AtomicVariableExample {
    private val atomicCounter = AtomicInteger(0)
    private val atomicBoolean = AtomicBoolean(false)
    private val atomicReference = AtomicReference("Initial")

    fun atomicIncrement() {
        val newValue = atomicCounter.incrementAndGet()
        println("Atomic counter: $newValue")
    }

    fun compareAndSet() {
        val success = atomicBoolean.compareAndSet(false, true)
        println("CAS result: $success, Value: ${atomicBoolean.get()}")
    }

    fun atomicUpdate() {
        atomicReference.updateAndGet { current ->
            println("Current: $current")
            "Updated"
        }
        println("Final: ${atomicReference.get()}")
    }

    fun getAndAdd() {
        val oldValue = atomicCounter.getAndAdd(5)
        println("Old: $oldValue, New: ${atomicCounter.get()}")
    }
}

// 5. Kotlin Coroutine Mutex
class CoroutineMutexExample {
    private val mutex = Mutex()
    private var sharedCounter = 0

    suspend fun safeIncrement() {
        mutex.withLock {
            sharedCounter++
            println("Counter: $sharedCounter (Coroutine: ${Thread.currentThread().name})")
        }
    }

    suspend fun tryLockExample() {
        if (mutex.tryLock()) {
            try {
                println("Mutex acquired")
                sharedCounter++
            } finally {
                mutex.unlock()
            }
        } else {
            println("Could not acquire mutex")
        }
    }
}

// 6. CountDownLatch
class CountDownLatchExample {
    fun demonstrateLatch() {
        val latch = CountDownLatch(3)

        // Create worker threads
        repeat(3) { index ->
            Thread {
                try {
                    println("Worker $index starting")
                    Thread.sleep((1000..2000).random().toLong())
                    println("Worker $index completed")
                } finally {
                    latch.countDown()
                }
            }.start()
        }

        // Main thread waits
        println("Main thread waiting for workers...")
        latch.await()
        println("All workers completed!")
    }

    fun awaitWithTimeout() {
        val latch = CountDownLatch(5)

        repeat(5) { index ->
            Thread {
                Thread.sleep(1000)
                latch.countDown()
            }.start()
        }

        // Wait with timeout
        if (latch.await(2, TimeUnit.SECONDS)) {
            println("Completed within timeout")
        } else {
            println("Timeout - not all completed")
        }
    }
}

// 7. CyclicBarrier
class CyclicBarrierExample {
    fun demonstrateBarrier() {
        val barrier = CyclicBarrier(3) {
            println("\n*** All threads reached barrier ***\n")
        }

        repeat(3) { index ->
            Thread {
                println("Thread $index: Phase 1")
                Thread.sleep(500)
                println("Thread $index: Waiting at barrier")

                try {
                    barrier.await()
                    println("Thread $index: Phase 2")
                } catch (e: Exception) {
                    println("Barrier error: ${e.message}")
                }
            }.start()
        }
    }
}

// 8. BlockingQueue (Producer-Consumer)
class BlockingQueueExample {
    private val queue = ArrayBlockingQueue<Int>(5)
    private var running = true

    fun startProducer() {
        Thread {
            var item = 0
            while (running) {
                try {
                    queue.put(item)
                    println("Produced: $item (Queue size: ${queue.size})")
                    item++
                    Thread.sleep(500)
                } catch (e: InterruptedException) {
                    break
                }
            }
        }.start()
    }

    fun startConsumer() {
        Thread {
            while (running) {
                try {
                    val item = queue.take()
                    println("Consumed: $item")
                    Thread.sleep(1000)
                } catch (e: InterruptedException) {
                    break
                }
            }
        }.start()
    }

    fun stop() {
        running = false
    }
}

// 9. Volatile Variables
class VolatileExample {
    @Volatile
    private var flag = false

    fun startFlagWatcher() {
        Thread {
            println("Watcher: Waiting for flag...")
            while (!flag) {
                // Busy wait (not recommended, use proper synchronization)
            }
            println("Watcher: Flag is now true!")
        }.start()
    }

    fun setFlag() {
        Thread.sleep(2000)
        flag = true
        println("Main: Flag set to true")
    }
}

// 10. Thread-safe Collections
class ThreadSafeCollectionsExample {
    // ConcurrentHashMap
    private val concurrentMap = ConcurrentHashMap<String, Int>()

    fun addToConcurrentMap() {
        repeat(10) { index ->
            Thread {
                concurrentMap["key$index"] = index
                println("Added key$index: $index")
            }.start()
        }

        Thread.sleep(1000)
        println("Map size: ${concurrentMap.size}")
    }

    // CopyOnWriteArrayList
    private val concurrentList = CopyOnWriteArrayList<String>()

    fun addToList() {
        repeat(5) { index ->
            Thread {
                concurrentList.add("Item $index")
                println("List size: ${concurrentList.size}")
            }.start()
        }

        Thread.sleep(1000)
        println("List: $concurrentList")
    }

    // Concurrent Linked Queue
    private val concurrentQueue = ConcurrentLinkedQueue<Int>()

    fun addToQueue() {
        repeat(5) { index ->
            Thread {
                concurrentQueue.offer(index)
                println("Queue size: ${concurrentQueue.size}")
            }.start()
        }

        Thread.sleep(1000)
        println("Queue: $concurrentQueue")
    }
}

// Main demonstration
fun demonstrateThreadSynchronization() {
    println("=== Android Kotlin Thread Synchronization Examples ===\n")

    // 1. Synchronized block
    println("--- 1. Synchronized Block ---")
    val syncExample = SynchronizedBlockExample()

    repeat(5) {
        Thread {
            syncExample.incrementCounter()
        }.start()
    }

    Thread.sleep(1000)

    // 2. ReentrantLock
    println("\n--- 2. ReentrantLock ---")
    val lockExample = ReentrantLockExample()

    repeat(3) {
        Thread {
            lockExample.performTask()
        }.start()
    }

    Thread.sleep(1000)

    // 3. Semaphore
    println("\n--- 3. Semaphore ---")
    val semaphoreExample = SemaphoreExample()

    repeat(5) { index ->
        Thread {
            semaphoreExample.accessResource(index)
        }.start()
    }

    Thread.sleep(3000)

    // 4. Atomic variables
    println("\n--- 4. Atomic Variables ---")
    val atomicExample = AtomicVariableExample()

    repeat(5) {
        Thread {
            atomicExample.atomicIncrement()
        }.start()
    }

    Thread.sleep(500)

    // 5. CountDownLatch
    println("\n--- 5. CountDownLatch ---")
    val latchExample = CountDownLatchExample()
    latchExample.demonstrateLatch()

    Thread.sleep(3000)

    // 6. Thread-safe collections
    println("\n--- 6. Thread-safe Collections ---")
    val collectionsExample = ThreadSafeCollectionsExample()
    collectionsExample.addToConcurrentMap()

    Thread.sleep(1000)

    println("\n=== All Thread Synchronization Examples Completed ===")
}

💻 Thread Pool Usage kotlin

🟡 intermediate ⭐⭐⭐⭐

Use thread pools efficiently with ExecutorService, coroutine dispatchers, and custom thread pool configurations

⏱️ 40 min 🏷️ kotlin, android, multithreading, thread pool
Prerequisites: Intermediate Kotlin, Understanding of thread pools
// Android Kotlin Thread Pool Examples
// Using ExecutorService, Coroutine Dispatchers, and Custom Thread Pools

import kotlinx.coroutines.*
import java.util.concurrent.*
import kotlin.system.measureTimeMillis

// 1. ExecutorService Thread Pools
class ExecutorServicePools {

    // Fixed thread pool
    fun fixedThreadPoolExample() {
        val executor = Executors.newFixedThreadPool(4)

        println("--- Fixed Thread Pool (4 threads) ---")

        val time = measureTimeMillis {
            val tasks = (1..8).map { taskId ->
                executor.submit {
                    println("Task $taskId starting on ${Thread.currentThread().name}")
                    Thread.sleep(1000)
                    println("Task $taskId completed")
                }
            }

            // Wait for all tasks to complete
            tasks.forEach { it.get() }
        }

        println("Total time: ${time}ms")
        executor.shutdown()
    }

    // Cached thread pool
    fun cachedThreadPoolExample() {
        val executor = Executors.newCachedThreadPool()

        println("\n--- Cached Thread Pool ---")

        val tasks = (1..10).map { taskId ->
            executor.submit<Int> {
                println("Task $taskId on ${Thread.currentThread().name}")
                Thread.sleep((100..500).random().toLong())
                taskId * 2
            }
        }

        tasks.forEach { future ->
            val result = future.get()
            println("Result: $result")
        }

        executor.shutdown()
    }

    // Single thread executor
    fun singleThreadExecutorExample() {
        val executor = Executors.newSingleThreadExecutor()

        println("\n--- Single Thread Executor ---")

        (1..5).forEach { taskId ->
            executor.submit {
                println("Task $taskId on ${Thread.currentThread().name}")
                Thread.sleep(200)
            }
        }

        executor.shutdown()
        executor.awaitTermination(5, TimeUnit.SECONDS)
    }

    // Scheduled executor
    fun scheduledExecutorExample() {
        val executor = Executors.newScheduledThreadPool(2)

        println("\n--- Scheduled Executor ---")

        // Schedule one-time task
        executor.schedule({
            println("Delayed task executed")
        }, 2, TimeUnit.SECONDS)

        // Schedule at fixed rate
        executor.scheduleAtFixedRate({
            println("Periodic task at ${System.currentTimeMillis()}")
        }, 0, 1, TimeUnit.SECONDS)

        // Run for 5 seconds then shutdown
        Thread.sleep(5000)
        executor.shutdown()
    }
}

// 2. Custom Thread Pool
class CustomThreadPoolExample {

    fun customThreadPoolExample() {
        // Create custom thread pool
        val threadFactory = ThreadFactory { runnable ->
            Thread(runnable).apply {
                name = "CustomPool-${System.currentTimeMillis()}"
                isDaemon = false
                priority = Thread.NORM_PRIORITY
            }
        }

        val executor = ThreadPoolExecutor(
            2, // Core pool size
            5, // Maximum pool size
            60L, // Keep-alive time
            TimeUnit.SECONDS,
            LinkedBlockingQueue(10), // Work queue
            threadFactory,
            ThreadPoolExecutor.CallerRunsPolicy() // Rejection policy
        )

        println("\n--- Custom Thread Pool ---")

        // Submit tasks
        for (i in 1..10) {
            try {
                executor.submit {
                    println("Task $i on ${Thread.currentThread().name}")
                    Thread.sleep(500)
                }
            } catch (e: RejectedExecutionException) {
                println("Task $i rejected")
            }
        }

        executor.shutdown()
        executor.awaitTermination(10, TimeUnit.SECONDS)
    }
}

// 3. Kotlin Coroutine Dispatchers
class CoroutineDispatchersExample {

    private val scope = CoroutineScope(SupervisorJob())

    // Main dispatcher (UI thread)
    fun mainDispatcherExample() {
        scope.launch(Dispatchers.Main) {
            println("Main dispatcher: ${Thread.currentThread().name}")
        }
    }

    // IO dispatcher (for IO operations)
    fun ioDispatcherExample() {
        scope.launch(Dispatchers.IO) {
            println("IO dispatcher: ${Thread.currentThread().name}")
            // Simulate IO operation
            delay(1000)
            println("IO operation completed")
        }
    }

    // Default dispatcher (CPU intensive)
    fun defaultDispatcherExample() {
        scope.launch(Dispatchers.Default) {
            println("Default dispatcher: ${Thread.currentThread().name}")
            // CPU intensive work
            var result = 0
            for (i in 1..1000000) {
                result += i
            }
            println("Computation result: $result")
        }
    }

    // Unconfined dispatcher
    fun unconfinedDispatcherExample() {
        scope.launch(Dispatchers.Unconfined) {
            println("Unconfined start: ${Thread.currentThread().name}")
            delay(100)
            println("Unconfined after delay: ${Thread.currentThread().name}")
        }
    }

    // Custom dispatcher with fixed thread pool
    fun customDispatcherExample() {
        val customDispatcher = newFixedThreadPoolContext(4, "CustomPool")

        scope.launch(customDispatcher) {
            println("Custom dispatcher: ${Thread.currentThread().name}")
            delay(500)
        }

        customDispatcher.close()
    }
}

// 4. Coroutine Async and Await
class CoroutineAsyncExample {

    private val scope = CoroutineScope(Dispatchers.Default)

    suspend fun parallelTasks(): Int = coroutineScope {
        println("\n--- Parallel Tasks with Async ---")

        val time = measureTimeMillis {
            val deferred1 = async {
                println("Task 1 starting")
                delay(1000)
                println("Task 1 completed")
                10
            }

            val deferred2 = async {
                println("Task 2 starting")
                delay(1500)
                println("Task 2 completed")
                20
            }

            val deferred3 = async {
                println("Task 3 starting")
                delay(500)
                println("Task 3 completed")
                30
            }

            // Wait for all and sum results
            val result = deferred1.await() + deferred2.await() + deferred3.await()
            println("Total result: $result")
        }

        println("Total time: ${time}ms")
        return@coroutineScope time.toInt()
    }

    suspend fun sequentialTasks(): Int = coroutineScope {
        println("\n--- Sequential Tasks ---")

        val time = measureTimeMillis {
            val result1 = withContext(Dispatchers.Default) {
                delay(1000)
                10
            }

            val result2 = withContext(Dispatchers.Default) {
                delay(1500)
                20
            }

            val result3 = withContext(Dispatchers.Default) {
                delay(500)
                30
            }

            println("Total result: ${result1 + result2 + result3}")
        }

        println("Total time: ${time}ms")
        return@coroutineScope time.toInt()
    }
}

// 5. Work Manager (Android Jetpack)
class WorkManagerExample {

    // This is a conceptual example
    // In actual Android code, you would use androidx.work.WorkManager

    fun enqueueWork() {
        // Concept: Enqueue one-time work
        // val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
        //     .setConstraints(Constraints.Builder()
        //         .setRequiredNetworkType(NetworkType.CONNECTED)
        //         .build())
        //     .build()
        //
        // WorkManager.getInstance(context).enqueue(workRequest)

        println("Work enqueued (conceptual example)")
    }

    fun enqueuePeriodicWork() {
        // Concept: Enqueue periodic work
        // val periodicWork = PeriodicWorkRequestBuilder<MyWorker>(
        //     15, TimeUnit.MINUTES
        // ).build()
        //
        // WorkManager.getInstance(context).enqueue(periodicWork)

        println("Periodic work enqueued (conceptual example)")
    }
}

// 6. ExecutorService with Future
class FutureExample {

    fun submitWithFuture() {
        val executor = Executors.newFixedThreadPool(3)

        println("\n--- ExecutorService with Future ---")

        // Submit callable tasks
        val futures = (1..5).map { taskId ->
            executor.submit<Int> {
                println("Task $taskId starting")
                Thread.sleep((500..1500).random().toLong())
                println("Task $taskId completed")
                taskId * 10
            }
        }

        // Process results as they complete
        futures.forEach { future ->
            try {
                val result = future.get()
                println("Future result: $result")
            } catch (e: Exception) {
                println("Future error: ${e.message}")
            }
        }

        executor.shutdown()
    }

    fun invokeAllExample() {
        val executor = Executors.newFixedThreadPool(4)

        val tasks = (1..10).map { taskId ->
            Callable<Int> {
                Thread.sleep(1000)
                taskId
            }
        }

        val time = measureTimeMillis {
            val futures = executor.invokeAll(tasks)

            futures.forEach { future ->
                println("Completed: ${future.get()}")
            }
        }

        println("InvokeAll time: ${time}ms")
        executor.shutdown()
    }
}

// 7. Completion Service
class CompletionServiceExample {

    fun completionServiceDemo() {
        val executor = Executors.newFixedThreadPool(4)
        val completionService = ExecutorCompletionService<Int>(executor)

        println("\n--- Completion Service ---")

        // Submit tasks
        (1..5).forEach { taskId ->
            completionService.submit(Callable<Int> {
                val sleepTime = (1000..3000).random().toLong()
                println("Task $taskId will take ${sleepTime}ms")
                Thread.sleep(sleepTime)
                taskId
            }
        }

        // Process as they complete
        repeat(5) {
            val future = completionService.take()
            val result = future.get()
            println("Completed task: $result")
        }

        executor.shutdown()
    }
}

// 8. ForkJoin Pool (Parallel processing)
class ForkJoinPoolExample {

    fun parallelSum(): Int {
        val pool = ForkJoinPool()

        println("\n--- ForkJoin Pool ---")

        val task = RecursiveSumTask(1, 1000000)
        val result = pool.invoke(task)

        println("Parallel sum result: $result")
        pool.shutdown()

        return result
    }

    class RecursiveSumTask(private val start: Int, private val end: Int) : RecursiveTask<Int>() {
        override fun compute(): Int {
            return if (end - start <= 10000) {
                // Compute directly
                (start..end).sum()
            } else {
                // Split task
                val mid = (start + end) / 2
                val leftTask = RecursiveSumTask(start, mid)
                val rightTask = RecursiveSumTask(mid + 1, end)

                leftTask.fork()
                val rightResult = rightTask.compute()
                val leftResult = leftTask.join()

                leftResult + rightResult
            }
        }
    }
}

// Main demonstration
suspend fun demonstrateThreadPoolUsage() {
    println("=== Android Kotlin Thread Pool Examples ===\n")

    // 1. ExecutorService pools
    val executorPools = ExecutorServicePools()
    executorPools.fixedThreadPoolExample()
    delay(2000)
    executorPools.cachedThreadPoolExample()
    delay(2000)
    executorPools.singleThreadExecutorExample()
    delay(1000)
    executorPools.scheduledExecutorExample()

    // 2. Custom thread pool
    val customPool = CustomThreadPoolExample()
    customPool.customThreadPoolExample()

    delay(2000)

    // 3. Coroutine dispatchers
    println("\n--- Coroutine Dispatchers ---")
    val dispatcherExample = CoroutineDispatchersExample()
    dispatcherExample.mainDispatcherExample()
    dispatcherExample.ioDispatcherExample()
    dispatcherExample.defaultDispatcherExample()
    dispatcherExample.unconfinedDispatcherExample()
    dispatcherExample.customDispatcherExample()

    delay(2000)

    // 4. Async and await
    val asyncExample = CoroutineAsyncExample()
    asyncExample.parallelTasks()
    asyncExample.sequentialTasks()

    delay(3000)

    // 5. Future example
    val futureExample = FutureExample()
    futureExample.submitWithFuture()
    delay(2000)
    futureExample.invokeAllExample()

    delay(2000)

    // 6. Completion service
    val completionExample = CompletionServiceExample()
    completionExample.completionServiceDemo()

    delay(5000)

    // 7. ForkJoin pool
    val forkJoinExample = ForkJoinPoolExample()
    forkJoinExample.parallelSum()

    println("\n=== All Thread Pool Examples Completed ===")
}

// Synchronous entry point
fun demonstrateThreadPoolUsageSync() {
    runBlocking {
        demonstrateThreadPoolUsage()
    }
}