Java无原生协程,在Java项目中集成使用Kotlin协程是否为可行方案?
Java 11项目调用Kotlin协程实现轻量级线程方案是否可行?
运行环境
Linux Mint 20 Java 11
我在Java项目中需要使用轻量级线程,协程是非常合适的选型,但Java本身没有原生协程支持,因此考虑在Java项目中调用Kotlin协程实现需求,具体实现方案如下:
在build.gradle中添加依赖:
implementation "org.jetbrains.kotlin:kotlin-stdlib" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2'
之后创建封装Kotlin协程的类:
import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking class CoroutineKotlin { fun runCoroutine() = runBlocking { // this: CoroutineScope launch { // launch a new coroutine and continue delay(3000L) // non-blocking delay for 3 seconds (default time unit is ms) println("Kotlin: From Kotlin coroutines!") // print after delay } println("Kotlin: Hello") // main coroutine continues while a previous one is delayed } fun runCoroutinesWithSuspend() = runBlocking { // this: CoroutineScope launch { doWorld() } println("Hello") } suspend fun doWorld() { delay(1000L) println("From Kotlin coroutines (suspend)!") } //Coroutines ARE light-weigh fun runManyCoroutines() = runBlocking { repeat(10_000) { // launch a lot of coroutines launch { delay(5000L) print(".") } } } }
然后在Java类中调用上述Kotlin类的方法:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.LocalDateTime; public class App { private static Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) { System.out.println("Java: Call Kotlin code from Java code, currentDate = " + LocalDateTime.now()); CoroutineKotlin coroutineKotlin = new CoroutineKotlin(); System.out.println("Java: Before call runCoroutine, currentDate = " + LocalDateTime.now()); coroutineKotlin.runCoroutine(); // call only after finish "runCoroutine()" System.out.println("Java: After call runCoroutine, currentDate = " + LocalDateTime.now()); System.out.println("\nJava: Before call runCoroutinesWithSuspend, currentDate = " + LocalDateTime.now()); coroutineKotlin.runCoroutinesWithSuspend(); // call only after finish "runCoroutinesWithSuspend()" System.out.println("Java: After call runCoroutinesWithSuspend, currentDate = " + LocalDateTime.now()); System.out.println("\nJava: Before call runManyCoroutines, currentDate = " + LocalDateTime.now()); coroutineKotlin.runManyCoroutines(); // call only after finish "runManyCoroutines()" System.out.println("\nJava: After call runManyCoroutines, currentDate = " + LocalDateTime.now()); } }
运行结果如下:
Java: Call Kotlin code from Java code, currentDate = 2021-10-15T15:44:58.391 Java: Before call runCoroutine, currentDate = 2021-10-15T15:44:58.392 Kotlin: Hello Kotlin: From Kotlin coroutines! Java: After call runCoroutine, currentDate = 2021-10-15T15:45:01.424 Java: Before call runCoroutinesWithSuspend, currentDate = 2021-10-15T15:45:01.425 Hello From Kotlin coroutines (suspend)! Java: After call runCoroutinesWithSuspend, currentDate = 2021-10-15T15:45:02.428 Java: Before call runManyCoroutines, currentDate = 2021-10-15T15:45:02.428 .............. 10000 dots here Java: After call runManyCoroutines, currentDate = 2021-10-15T15:45:07.538
从运行结果可见,2个非挂起方法和1个suspend挂起方法均能在Java代码中成功调用,第三个方法创建的10000个协程也能正常运行无异常,请问该方案是否为合适的解决方案?
回答
这个方案在Java 11的环境下是完全可行的,属于当前环境下性价比很高的解决方案,适配性和稳定性都有保障,但有几个可以优化的点:
- 你当前所有对外暴露的协程方法都用了
runBlocking包裹,调用时会阻塞当前的Java线程,只用到了协程轻量、支持高并发创建的特性,如果后续需要异步非阻塞的能力,可以调整封装逻辑,把执行结果通过CompletableFuture回调给Java侧,不需要阻塞调用线程。 - 你现在用的
kotlinx-coroutines-core-jvm:1.5.2版本比较旧,建议升级到当前的稳定版,新版本修复了不少调度bug,性能也有提升。 - 如果后续项目会升级到Java 19及以上版本,可以直接切换到JDK原生的虚拟线程,不需要额外引入Kotlin相关依赖,和现有Java并发工具的适配性也更好。
内容的提问来源于stack exchange,提问作者Alexei
相关产品推荐
相关产品推荐

