不恰当的阻塞方法调用:如何在 Kotlin 中修复

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

“Inappropriate blocking method call”:当 Kotlin 报错而您不理解原因时

\n\n

您正在使用 Kotlin 编写代码,使用协程,一切看起来都很完美。然后——砰!——编译器或静态分析器(例如 IntelliJ IDEA)发出警告:“Inappropriate blocking method call”。熟悉吗?如果您曾经见过这条消息,您就会知道:它总是在最不合时宜的时候出现。如果没有见过,那算您幸运,但最好提前做好准备。

\n\n

这个错误不仅仅是 IDE 的任性。这是一个信号:您正在做一些可能会“扼杀”应用程序性能的事情。在本文中,我们将分析这个警告的含义、它出现的原因,以及最重要的是——如何让“inappropriate blocking method call”变得 appropriate(即恰当)。我们将比较三种方法,用 Kotlin 编写代码,并找出哪种方法在何时更合适。开始吧!

\n\n

什么是“inappropriate blocking method call”?

\n\n

简而言之:Kotlin(及其生态系统)建立在非阻塞执行的理念之上。当您使用协程时,假设您不会通过诸如 Thread.sleep() 或 InputStream.read() 之类的调用来“休眠”线程。这会阻塞线程,而协程恰恰应该释放线程。

\n\n

一个典型的例子是在协程内部调用 Thread.sleep(1000)。分析器看到这一点并会大喊:“嘿!你阻塞了线程!请使用 delay()!”。但问题不仅仅在于 sleep。任何可能阻塞线程的调用(读取文件、数据库操作、同步 HTTP 请求)都可能触发此警告。

\n\n

为什么这很糟糕?因为协程在线程池上工作。如果一个线程被阻塞,它就无法执行其他协程。在最坏的情况下,您可能会面临线程“饥饿”和性能下降的风险。

\n\n

方法对比:如何修复阻塞调用

\n\n

我们将考虑三种出现错误的场景,并展示如何规避它们。每种方法都将附有 Kotlin 代码示例以及优缺点分析。最后是一个汇总表格。

\n\n

方法 1:使用 Dispatchers.IO

\n\n

最简单且经常推荐的方法是将阻塞代码包装在 withContext(Dispatchers.IO) 中。这个调度器专门用于阻塞的输入/输出操作。

\n\n
import kotlinx.coroutines.*\n\nsuspend fun readFile(path: String): String = withContext(Dispatchers.IO) {\n    // 阻塞调用(例如,读取文件)\n    java.io.File(path).readText()\n}\n\nfun main() = runBlocking {\n    val content = readFile("example.txt")\n    println(content)\n}
\n\n

优点:

\n
    \n
  • 代码改动最小。
  • \n
  • 清晰的分离:阻塞代码在单独的线程池上执行。
  • \n
  • 不需要第三方库。
  • \n
\n\n

缺点:

\n
    \n
  • 仍然会阻塞线程(尽管不是主线程)。
  • \n
  • 在大量并发调用的情况下,可能会耗尽线程池(默认 64 个线程)。
  • \n
\n\n

何时使用:如果您有少量的阻塞操作(例如,启动时加载配置)或者您无法更改库。

\n\n

方法 2:替换为非阻塞替代方案

\n\n

理想但并非总是可行的方案是将阻塞调用替换为其非阻塞版本。例如,使用 delay() 代替 Thread.sleep(),使用异步 HTTP 客户端(Ktor、带协程的 OkHttp)代替同步 HTTP 客户端。

\n\n
import kotlinx.coroutines.*\n\nsuspend fun fetchData(): String {\n    // 非阻塞延迟\n    delay(1000)\n    // 异步 HTTP 请求(以 Ktor 为例)\n    return httpClient.get("https://api.example.com/data").body()\n}\n\nfun main() = runBlocking {\n    val data = fetchData()\n    println(data)\n}
\n\n

优点:

博客

书籍推荐