当前位置: 首页 > article >正文

Kotlin 使用虚拟线程并在低版本中自动切换到协程

在 Java 虚拟线程正式发布后,Kotlin 开发者迎来了并发编程的新选择。本文将揭示如何构建一个智能化的执行方法,在支持虚拟线程的环境(Java 19+)中享受轻量级线程的优势,同时在低版本运行时自动降级到协程机制,实现真正的版本自适应并发控制。

如何创建一个虚拟线程

在虚拟线程发布后有多种新增的API创建方式通过ExecutorsThread 等。在这些类中现在了一些方法用于创建虚拟线程,同样的可以通过是否有这些方法来判断是否支持虚拟线程

  1. Executors
val p = Executors.newVirtualThreadPerTaskExecutor()
  1. Thread
Thread.ofVirtual().start {
    runBlocking {
        println("VirtualThread")
    }
}

如何检测是否支持虚拟线程

如上面所说,虚拟线程发布后新增了API,通过反射访问API,如果不存在说明不存在API。不存在API就意味着不支持虚拟线程

/**
* 判断是否支持虚拟线程
* */
fun isSupportVirtualThread(): Boolean {
    return virtualThreadExecutor != null
}

/**
* 反射获取虚拟线程的ExecutorService
* */
private val virtualThreadExecutor: ExecutorService? by lazy {
    runCatching {
        val clazz = Executors::class.java
        val method = clazz.getMethod("newVirtualThreadPerTaskExecutor")
        method.isAccessible = true
        method.invoke(null) as ExecutorService
    }.getOrNull()
}

开启虚拟线程,不存在则开启协程

通过检查是否支持虚拟线程来判断开启虚拟线程还是协程

if (isSupportVirtualThread()) {
      Thread.ofVirtual().start {
          runBlocking {
              block()
          }
      }
} else {
    CoroutineScope(Dispatchers.IO).launch {
        block()
    }
}

下面对其进行简单封装一下,方法返回一个封装类,类可以对虚拟线程和协程进行等待等操作


fun <T : Any> CoroutineScope.runLightweightThread(block: suspend () -> T) = runLightweightThread(this) {
    block()
}

fun <T : Any> runLightweightThread(
    cs: CoroutineScope = CoroutineScope(Dispatchers.IO),
    block: suspend () -> T
): LightweightThread<T> {
    return if (isSupportVirtualThread()) {
        LightweightThread(virtualThreadExecutor!!.submit { runBlocking { block() } })
    } else {
        LightweightThread(job = cs.async { block() })
    }
}

class LightweightThread<T : Any>(
    private val thread: Future<*>? = null,
    private val job: Deferred<T>? = null
) {
    suspend fun coAwait(): T? = withContext(Dispatchers.IO) {
        thread?.get()?.let { it as T }
    } ?: job?.await()

    fun await(): T? {
        return runBlocking {
            job?.await()
        } ?: thread?.get()?.let { it as T }
    }

    fun join() {
        thread?.get()
        runBlocking {
            job?.join()
        }
    }

    fun cancel() {
        thread?.cancel(true)
        job?.cancel()
    }
}

如何开一个虚拟线程的协程

通过 asCoroutineDispatcher 方法可以将ExecutorService 转为一个协程调度器

fun main() {
    CoroutineScope(Dispatchers.VT).launch {
        println(123)
    }
}

val Dispatchers.VT: CoroutineDispatcher by lazy {
    if (isSupportVirtualThread()) {
        virtualThreadExecutor!!.asCoroutineDispatcher()
    } else {
        Dispatchers.IO
    }
}

http://www.kler.cn/a/536309.html

相关文章:

  • .net的一些知识点6
  • 自动化测试、压力测试、持续集成
  • 概念AIGC
  • PostgreSQL:字符串函数用法
  • 109,【1】攻防世界 web 题目名称-文件包含
  • TensorFlow是个啥玩意?
  • zabbix v7.2.3容器运行Proxy代理服务器启用IPV6访问
  • 代码随想录算法【Day38】
  • SQL Server查询计划操作符(7.3)——查询计划相关操作符(6)
  • 第4节课:控制结构 - 条件语句、循环语句
  • 本地私有化部署 DeepSeek Dify ,告别“服务器繁忙,请稍后再试”
  • 小米官博宣布:首款AI眼镜即将发布
  • Java实现网络安全编程数字信封 网络安全 java
  • 深入解析:如何利用 Python 爬虫获取商品 SKU 详细信息
  • 深入理解 YUV Planar 和色度二次采样 —— 视频处理的核心技术
  • 第30节课:前端架构与设计模式—构建高效可维护的Web应用
  • 《金字塔原理》笔记
  • 【JS】element-ui 中 table的select事件
  • source 与 shell 之详解(Detailed Explanation of Source and Shell)
  • 集合类不安全问题
  • tqdm用法教程
  • 【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter5-基本引用类型
  • Python调取本地MongoDB招投标数据库,并结合Ollama部署的DeepSeek-R1-8B模型来制作招投标垂直领域模型
  • Git(分布式版本控制系统)系统学习笔记【并利用腾讯云的CODING和Windows上的Git工具来实操】
  • 7.list
  • Kotlin协程详解——协程取消与超时