当前位置: 首页 > 知识库问答 >
问题:

kotlin协程在网络请求中如何使用?

井洲
2023-05-02

我在测试在kotlin的协程里使用网络io是否会导致线程阻塞

suspend fun main() {
    Executors.newSingleThreadExecutor().asCoroutineDispatcher().use {
        dispatcher->  supervisorScope {
            async(dispatcher) {
                while (true){
                    delay(1000)
                    println("打印${Thread.currentThread()}")
                }
            }
            async(dispatcher) {
                val socket = Socket("127.0.0.1", 12365)
                var read = socket.getInputStream()
                while (true){
                    println("读取成功${read.read()},${Thread.currentThread()}")
                    yield()
                }
            }
        }
    }
}

测速结果是InputStream.read确实导致线程阻塞了,而不是挂起。

那么运行在统一个线程下的其他协程也不能运行了,我知道可以使用

          async(Dispatchers.IO) {
                
            }
        withContext(Dispatchers.IO){
            
        }

这些方式把网络请求放入其他线程
但是我想知道的是如果这两个协程都必须运行在同一个线程里时,是否可以通过修改代码(比如异步io等方式)确保第一个协程能每秒打印一次,第二个协程能在接收到数据时及时打印。

共有1个答案

程鸿煊
2023-05-02

你用 Java NIO 就好了:

import kotlinx.coroutines.*
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.channels.AsynchronousSocketChannel
import java.nio.channels.CompletionHandler
import java.util.concurrent.Executors

suspend fun main() {
    Executors.newSingleThreadExecutor().asCoroutineDispatcher().use { dispatcher ->
        supervisorScope {
            async(dispatcher) {
                while (true) {
                    delay(1000)
                    println("打印${Thread.currentThread()}")
                }
            }
            async(dispatcher) {
                val socketChannel = AsynchronousSocketChannel.open()
                val address = InetSocketAddress("127.0.0.1", 12365)
                socketChannel.connect(address).get()

                while (true) {
                    val buffer = ByteBuffer.allocate(1024)
                    socketChannel.read(buffer, null, object : CompletionHandler<Int, Void?> {
                        override fun completed(result: Int, attachment: Void?) {
                            buffer.flip()
                            println("读取成功${buffer.get()},${Thread.currentThread()}")
                        }

                        override fun failed(exc: Throwable, attachment: Void?) {
                            println("读取失败: $exc")
                        }
                    })
                    yield()
                }
            }
        }
    }
}
 类似资料:
  • Mpx提供了网络请求库fetch,抹平了微信,阿里等平台请求参数及响应数据的差异;同时支持请求拦截器,请求取消等 使用说明 import mpx from '@mpxjs/core' import mpxFetch from '@mpxjs/fetch' mpx.use(mpxFetch) // 第一种访问形式 mpx.xfetch.fetch({ url: 'http://xxx.com' }

  • 最近,我通过学习CodeLabs教程学习了kotlin coroutine。经过一些实践,我想知道我是否可以用java编写相同的代码。首先,我在MyKotlinFragment中编写了一个简单的kotlin代码。kt文件如下: 在我的片段中调用了;它起作用了。 接下来,我打开了一个名为MyRoutineFragment的java文件。java在同一个项目中,但我无法让它工作。 我无法将第一个文件转

  • OKHTTP在某种程度上支持并发请求API吗? 如果没有,最好的实现方法是什么?

  • 类似于Ajax,QAP实现了Fetch功能,能够简单的异步的获取资源。 GET QN.fetch('http://121.42.141.44:8888', { body: '', method: 'GET', mode: 'same-origin', dataType: 'text', }) .then(response => { return respon

  • request 指的是小程序中的网络请求,在 mpvue 框架中可以通过小程序提供的原生 API wx.request 来进行相关的处理。但是在这里推荐一个第三方的网络请求库 fly。之所以推荐这个第三方库,是因为可以在多个端上实现代码的复用,目前已支持的有 Node.js 、微信小程序 、Weex 、React Native 、Quick App。 在 mpvue 中如何使用 安装 npm in

  • Chrome提供了较为完整的方法供扩展程序分析、阻断及更改网络请求,同时也提供了一系列较为全面的监听事件以监听整个网络请求生命周期的各个阶段。网络请求的整个生命周期所触发事件的时间顺序如下图所示。 网络请求的生命周期,图片来自developer.chrome.com 要对网络请求进行操作,需要在Manifest中声明webRequest权限以及相关被操作的URL。如需要阻止网络请求,需要声明web