如何使用协程实现非阻塞

时间:2019-01-04 20:34:25

标签: kotlin coroutine kotlin-coroutines

我正在尝试以一种比线程获得更多网络调用的方式实现非IO阻塞协程(kotlin)。很明显,如何以不阻塞主线程的方式使用协程,但是最终每个协程都在一个分支中运行,并且网络调用该线程的块(为了进行比较,使用NodeJS可以重用工作线程,而其他请求却是等待回应回来)。

我的用例是,对于每个传入请求,我需要进行2-3个独立的外部调用,汇总响应并返回。顺序执行此操作会浪费时间。并行执行此操作将要求我的服务运行的传入线程数大约是输入线程数的2-3倍(仅等待IO就使其线程数约为1K)。

许多协程示例都使用delay,从而允许同时为多个协程重用线程。但是,通过实际使用网络呼叫的实际使用案例,我无法实现这一目标。

我想念什么?如何暂停协程,直到外部服务响应?

例如,此示例仅在5个线程上运行,但是在1000个调用中重用了这些线程,因此它们均在〜100ms(每个交易为100ms)内结束

val myPool = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
runBlocking {
  (1..1000).forEach {
    launch(myPool) {
      delay(100)
    }
  }
}

与此相反,它实际上仅在5个线程上运行5个并发调用,并仅在完成一次后继续进行下一个调用。 我希望所有调用都“并行”执行,利用等待响应的同时发送请求的方式-就像在NodeJS中所做的一样

val restTemplate = RestTemplate()
val myPool = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
runBlocking {
  (1..1000).forEach {
    launch(myPool) {
      restTemplate.getForObject("http://myTest.com", String::class.java) // Say it takes 100ms to response
    }
  }
}

2 个答案:

答案 0 :(得分:2)

Kotlin协程并不是将阻塞网络操作变成非阻塞的魔力。它们仅允许您使用异步网络实现,而不会浪费期货和回调。

所以,为了继续进行,

  • 第1步。找到一个异步REST库
  • 第2步。编写一些Kotlin代码,以将库的基于本地回调或未来的API链接到Kotlin协程。

答案 1 :(得分:0)

“我希望所有调用“并行”执行!

为什么不把Executors.newFixedThreadPool(5)去掉,把Dispatchers.IO给他自己运行的协程?

runBlocking {
  (1..1000).forEach {
    launch(Dispatchers.IO) {
      delay(100)
    }
  }
}
相关问题