在 Kotlin 中使用线程还是协程更好?

ari*_*fng 2 multithreading kotlin kotlin-coroutines

我正在从应用程序发送邮件。由于邮件发送需要时间并阻塞主线程,我正在创建一个新线程并将邮件发送任务移交给新线程。对于发送邮件的大量并发请求,我必须创建大量线程。但是创建线程似乎很慢。

我的问题是,如果我使用 Kotlin 的协程,它的性能是否比线程更好?

某种解释或提示是非常可观的。

Mat*_*ans 7

在 Kotlin 中,您几乎应该总是使用协程来管理并发性。

但是,如果您必须进行长时间的阻塞调用,无论如何它都会阻塞一个线程,并且您应该确保它不会阻塞可能使您的应用程序停顿的线程。

在 Kotlin 中,当您需要一个协程在不同的或特殊的线程上运行时,您可以使用“调度程序”,它几乎相当于一个线程池。 Dispatchers.IO专门用于运行冗长的阻塞 I/O 操作,例如发送电子邮件。

使用它就像:

withContext(Dispatchers.IO) {
    sendEmail(...)
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*hin 5

TL;DR - 在 Kotlin 中工作时总是使用协程

线程具有相对较大的内存占用——每个线程大约有 1MB 的 VM 内存。如果您为每个任务创建一个线程,那么您将面临内存不足的风险。相比之下,协程相对较小,占用 VM 的几 KB 内存。

新线程的创建相对较慢,因为它要通过操作系统。操作系统对协程一无所知,因此产生一个新的协程相对较快。

出于同样的原因,线程之间的上下文切换比挂起的协程之间的上下文切换要昂贵得多。

此外,由于结构化并发,协程不太容易泄漏。


Mar*_*nik 5

我的问题是,如果我使用 Kotlin 的协程,它是否能提供比线程更好的性能?

协程并不是线程的快速替代品。根本区别在于您使用的 API 类型。经验法则是这样的:

  • 阻塞 API -> 使用线程池
  • 非阻塞(异步)API -> 使用协程

因此,如果您能够掌握异步邮件发送 API,那么请务必使用协程。但如果你被阻塞的 API 所困扰,协程不会给你带来太多价值。它们可以让从 UI 线程中传输阻塞操作变得更方便,但不管有没有协程,其机制都是相同的。