Kotlin 1.3:如何在单独的线程上执行块?

时间:2018-10-26 14:34:15

标签: kotlin kotlinx.coroutines

我一直在阅读有关Kotlin中的并发信息,并以为我开始了解它了……然后我发现async()在1.3中已被弃用,我又回到了开始。

这就是我想要做的:创建一个线程(不幸的是,它必须是线程而不是托管池),然后能够对该线程执行异步块,并返回{{1 }}实例,让我可以使用Deferred

在Kotlin中推荐使用哪种方法?

3 个答案:

答案 0 :(得分:3)

不建议使用该消息,而是建议使用像async这样的显式范围调用GlobalScope.async {}

这也是不推荐使用的方法的实际实现。

通过删除顶级async函数,您不会遇到隐式作用域或错误导入的问题。

答案 1 :(得分:2)

1。单线程协程调度程序

  

这就是我想要做的:创建一个线程(不幸的是,它必须是线程而不是托管池)

仅当您准备深入研究并实现自己的协程调度程序时,才选择启动原始线程来处理协程。 Kotlin通过包装在调度程序中的单线程执行程序服务为您的需求提供支持。请注意,如果您使用需要线程工厂的重载,这仍然使您几乎可以完全控制如何启动线程:

val threadPool = Executors.newSingleThreadExecutor {
    task -> Thread(task, "my-background-thread")
}.asCoroutineDispatcher()

2。 async-awaitwithContext

  

然后可以在该线程上执行异步块,并返回Deferred实例,这些实例将允许我使用.await()。

确保您确实需要async-await,这意味着您除了其他用途之外还需要它

val result = async(singleThread) { blockingCal() }.await()

仅在需要启动后台任务,在调用线程上执行更多操作,然后在其上执行async-await时,才使用await()

协程的大多数新用户由于对其他语言的熟悉而锁上了该机制,并将其用于上述的普通顺序代码,但避免了阻塞UI线程的陷阱。 Kotlin具有“默认顺序”的哲学,这意味着您应该改为使用

val result = withContext(singleThread) { blockingCall() }

这不会在后台线程中启动新的协程,而是将当前协程的执行转移到该协程上,并在完成后将其返回。

3。不推荐使用的顶级async

  

然后我发现async()在1.3中已弃用

生成自由运行的后台任务通常是不明智的做法,因为它在出现错误甚至是异常执行模式时表现不佳。您的调用方法可能不返回await而返回或失败,但是后台任务将继续。如果应用程序反复重新输入生成后台任务的代码,则您的singleThread执行者的队列将不受限制地增长。所有这些任务将无目的地运行,因为它们的请求者早已消失。

这就是为什么Kotlin不推荐使用顶级协程生成器,现在您必须使用协程范围明确地限定它们的使用期限,您必须根据用例定义其生命周期。当示波器的生命周期用尽时,它将自动取消其中生成的所有协程。

在Android的示例中,这相当于将协同程序范围绑定到Activity的生存期,如CoroutineScope的KDoc中所述。

答案 2 :(得分:0)

让我推荐以下解决方案:Kotlin coroutines with returned value

它将任务并行化为3个后台线程(所谓的“三元组池”),但是很容易按照您的要求通过将tripletsPool替换为backgroundThread来将其更改为单线程,如下所示:

private val backgroundThread = ThreadPoolExecutor(1, 1, 5L, TimeUnit.SECONDS, LinkedBlockingQueue())