Cooperatively Multitasking Parallelism Concurrency Not useful in Realtime context Useful in Realtime context Context Switching needs system call Context Switching doesn't need system call
Cooperatively Multitasking Parallelism Concurrency Not useful in Realtime context Useful in Realtime context Context Switching needs system call Context Switching doesn't need system call Synchronization Primitives (Mutexes, Semaphores) are required Mutexes or Semaphores are not required
= System.currentTimeMillis() val job = launch(Dispatchers.Default) { var nextPrintTime = startTime var i = 0 while (i < 5) { // computation loop, just wastes CPU // print a message twice a second if (System.currentTimeMillis() >= nextPrintTime) { println("I'm sleeping ${i++} ...") nextPrintTime += 500L } } } delay(1300L) // delay a bit println("main: I'm tired of waiting!") job.cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.") }
startTime = System.currentTimeMillis() val job = launch(Dispatchers.Default) { var nextPrintTime = startTime var i = 0 while (isActive) { // cancellable computation loop // print a message twice a second if (System.currentTimeMillis() >= nextPrintTime) { println("I'm sleeping ${i++} ...") nextPrintTime += 500L } } } delay(1300L) // delay a bit println("main: I'm tired of waiting!") job.cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.") }
job = launch { try { repeat(1000) { i -> println("I'm sleeping $i ...") delay(500L) } } finally { println("I'm running finally") } } delay(1300L) // delay a bit println("main: I'm tired of waiting!") job.cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.") }
= launch { try { repeat(1000) { i -> println("I'm sleeping $i ...") delay(500L) } } finally { withContext(NonCancellable) { println("I'm running finally") delay(1000L) println("Delayed for 1 sec because I'm non-cancellable") } } } delay(1300L) // delay a bit println("main: I'm tired of waiting!") job.cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.")
10 } suspend fun doTaskTwo(): Int { delay(1000L) return 20 } fun main() = runBlocking { val time = measureTimeMillis { val t1 = doTaskOne() val t2 = doTaskTwo() println("Result - ${t1 + t2}") } println("Time Taken - $time") }
not carry any resulting value 1. async returns Deferred 2. async carries resulting value They both start a coroutine which runs concurrently with all other coroutines.
called CoroutineContext. 2. CoroutineContext is an interface in implementation. 3. It has various Elements. 4. Major elements are: a. Job - represents a background job b. CoroutineDispatcher - represents which thread the coroutine uses for its execution
println("main > runBlocking > launch") println("running in - ${Thread.currentThread().name}") } } Dispatcher for child coroutine is not confined. So will work with main thread.
println("main > runBlocking > launch") println("running in - ${Thread.currentThread().name}") } } Default dispatcher. This is also used when coroutine is launched in GlobalScope. This uses a shared pool of background threads.
println("main > runBlocking > launch") println("running in - ${Thread.currentThread().name}") } } Creates a new dedicated thread for the coroutine to run.
to work with a single thread. Confined to work with the thread inherited from parent CoroutineContext Unconfined coroutine dispatcher starts in the caller thread but until the first suspension. After the first suspension, it resumes in a thread defined by the suspension function which was called.
CoroutineScope. 2. CoroutineScope has a CoroutineContext. 3. CoroutineContext has a set of elements including the Job. 4. Job can be fun main() = runBlocking { println("My Job is - ${coroutineContext[Job]}") }
= MainScope() fun onDestroy() { mainScope.cancel() } // to be continued ... } class MainActivity : CoroutineScope by CoroutineScope(Dispatchers.Default) { // to be continued ... }
{ // to be continued ... fun doSomething() { // launch ten coroutines, each working for a different time repeat(10) { i -> launch { delay((i + 1) * 200L) // delay 200ms, 400ms, ... etc println("Coroutine $i is done") } } } fun onDestroy() { cancel() } }
val n = 100 // number of coroutines to launch val k = 1000 // times an action is repeated by each coroutine val time = measureTimeMillis { val jobs = List(n) { launch { repeat(k) { action() } } } jobs.forEach { it.join() } } println("Completed ${n * k} actions in $time ms") }
= runBlocking { GlobalScope.massiveRun { counter++ } println("Counter - $counter") } Volatile guaratee Atomic Reads and Writes operation on a variable. It doesn’t provide atomicity on complex actions (Increment in this case).
private var counter = 0 fun main() = runBlocking { GlobalScope.massiveRun { // run each coroutine with DefaultDispathcer withContext(counterContext) { // but confine each increment to the single-threaded context counter++ } } println("Counter = $counter") }