【问题标题】:Can I take advantage of Kotlin's Coroutines by using them in Java code?我可以通过在 Java 代码中使用 Kotlin 的协程来利用它们吗?
【发布时间】:2017-05-24 08:50:43
【问题描述】:

我的目标是什么?

我的目标是能够从 Java 中使用 Kotlin 的协程系统。我希望能够在给定的时间内暂停执行中途,然后在给定的时间过去后在该位置恢复。在 Java 中,我希望能够执行允许在不以异步方式暂停执行的任务,例如:

//example 1
someLogic();
pause(3000L); //3 seconds
someMoreLogic();

//example 2
while(true) {
    someContinuedLogic();
    pause(10000L); //10 seconds
}

我有什么问题?

正如预期的那样,我可以从 Kotlin 完美地执行协程,但是对于 Java,它变得很棘手,因为代码的 Java 部分一次执行整个块而没有任何暂停,而 Kotlin 块正确地暂停1,然后是 4 秒。

我的问题是什么?

甚至可以使用 Kotlin 作为 Java 中协程的主干吗?如果是这样,我做错了什么? 您可以在下面找到显示我如何尝试在 Java 中使用 Kotlin 协程的源代码。

KtScript 类

abstract class KtScript {

    abstract fun execute()

    fun <T> async(block: suspend () -> T): CompletableFuture<T> {
        val future = CompletableFuture<T>()
        block.startCoroutine(completion = object : Continuation<T> {
            override fun resume(value: T) {
                future.complete(value)
            }
            override fun resumeWithException(exception: Throwable) {
                future.completeExceptionally(exception)
            }
        })
        return future
    }

    suspend fun <T> await(f: CompletableFuture<T>): T =
            suspendCoroutine { c: Continuation<T> ->
                f.whenComplete { result, exception ->
                    if (exception == null)
                        c.resume(result)
                    else
                        c.resumeWithException(exception)
                }
            }

    fun pause(ms: Long): CompletableFuture<*> {
        //todo - a better pausing system (this is just temporary!)
        return CompletableFuture.runAsync {
            val currentMs = System.currentTimeMillis()
            while (System.currentTimeMillis() - currentMs < ms) {
                /* do nothing */
            }
        }
    }

}

Kotlin 执行代码

fun main(args: Array<String>) {
    ScriptTestKotlin().execute()
}

class ScriptTestKotlin : KtScript() {
    override fun execute() {
        println("Executing Kotlin script from Kotlin...")
        val future = async {
            await(pause(1000L))
            println("   1 second passed...")
            await(pause(4000L))
            println("   5 seconds passed...")
        }
        future.get() //wait for asynchronous task to finish
        println("Finished!")
    }
}

Kotlin 执行结果

Executing Kotlin script from Kotlin...
   1 second passed...
   5 seconds passed...
Finished!

Java 执行代码

public class ScriptTestJava extends KtScript {

    public static void main(String[] args) {
        new ScriptTestJava().execute();
    }

    @Override
    public void execute() {
        System.out.println("Executing Kotlin script from Java...");
        CompletableFuture<?> future = async(continuation -> {
            await(pause(1000L), continuation);
            System.out.println("    1 second passed...");
            await(pause(4000L), continuation);
            System.out.println("    5 seconds passed...");
            return continuation;
        });
        try {
            future.get(); //wait for asynchronous task to finish
        } catch(Exception e) {
            e.printStackTrace();
        }
        System.out.println("Finished!");
    }
}

Java 执行结果

Executing Kotlin script from Java...
    1 second passed...
    5 seconds passed...
Finished!

^^^ 不幸的是,Java 中跳过了暂停。 ^^^

【问题讨论】:

  • 你为什么不改用 Kotlin 呢?

标签: java kotlin coroutine


【解决方案1】:

Kotlin 协程是通过对代码的编译器转换来实现的,这显然只能由 kotlinc 完成。

所以,不,Java 不能使用 Kotlin 的协程机制,因为它是一个编译时特性。

【讨论】:

  • 如果您的库是使用协同程序用 Kotlin 编写的,并作为 JAR 包含在 Java 项目中会怎样。 Java 是否能够利用用 Kotlin 编写的调用协程的方法?
  • 从 java POV 来看,这样的库看起来就像带有回调和一些对 kotlinx.coroutines 库类的方法调用的普通字节码。所以与任何其他异步技术没有什么不同
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2021-10-28
  • 1970-01-01
  • 2011-09-05
相关资源
最近更新 更多