Why not use GlobalScope.launch?

前端 未结 3 1578
-上瘾入骨i
-上瘾入骨i 2020-12-01 10:45

I read that usage of Globalscope is highly discouraged, here.

I have a simple use-case. For every kafka message (let\'s say a list of Ids) that I receiv

3条回答
  •  天命终不由人
    2020-12-01 11:32

    In your link it states:

    Application code usually should use application-defined CoroutineScope, using async or launch on the instance of GlobalScope is highly discouraged.

    My answer addresses this.

    Generally speaking GlobalScope may bad idea, because it is not bound to any job. You should use it for the following:

    Global scope is used to launch top-level coroutines which are operating on the whole application lifetime and are not cancelled prematurely.

    Which does not seem to be your usecase.


    For more information there is a passage in the official docs at https://kotlinlang.org/docs/reference/coroutines/basics.html#structured-concurrency

    There is still something to be desired for practical usage of coroutines. When we use GlobalScope.launch we create a top-level coroutine. Even though it is light-weight, it still consumes some memory resources while it runs. If we forget to keep a reference to the newly launched coroutine it still runs. What if the code in the coroutine hangs (for example, we erroneously delay for too long), what if we launched too many coroutines and ran out of memory? Having to manually keep a reference to all the launched coroutines and join them is error-prone.

    There is a better solution. We can use structured concurrency in our code. Instead of launching coroutines in the GlobalScope, just like we usually do with threads (threads are always global), we can launch coroutines in the specific scope of the operation we are performing.

    In our example, we have main function that is turned into a coroutine using runBlocking coroutine builder. Every coroutine builder, including runBlocking, adds an instance of CoroutineScope to the scope of its code block. We can launch coroutines in this scope without having to join them explicitly, because an outer coroutine (runBlocking in our example) does not complete until all the coroutines launched in its scope complete. Thus, we can make our example simpler:

    import kotlinx.coroutines.*
    
    fun main() = runBlocking { // this: CoroutineScope
        launch { // launch new coroutine in the scope of runBlocking   
            delay(1000L)   
            println("World!")    
        }   
        println("Hello,")  
    }
    

    So in essence it is discouraged, because it forces you to keep references and use join, which can be avoided with structured concurrency. (See code example above.) The article covers many of the subtleties.

提交回复
热议问题