将Kotlin协程与Nashorn一起使用

时间:2019-07-12 19:55:50

标签: multithreading kotlin nashorn kotlin-coroutines

我正在使用Nashorn在Kotlin项目中运行一些JS脚本。一些脚本大量使用线程,并且由于其中一些线程的长期运行特性,因此希望使用协程代替,以便在需要重新加载脚本时可以取消协程(这种情况经常发生)。但是,我遇到的麻烦比我想象的要多。

以下是使用Java Thread类的目标JS代码:

new Thread(function() {
    Thread.sleep(2000);
    print('hello');
}).start();

为了使用协程,我做了一个简单的ThreadWrapper:

class ThreadWrapper(private val method: Any) {
    val thread = GlobalScope.launch {
        newThread(this@ThreadWrapper)

        suspendCoroutine<Unit> { cont ->
            // call method, which is a nashorn scriptobjectmirror, and pass in cont
            // as the first argument
            JSLoader.callActualMethod(method, cont)
        }
    }

    fun cancel() {
        thread.cancel(CancellationException("Stopped by ThreadWrapper"))
    }

    companion object {
        @JvmStatic
        suspend fun sleep(timeMillis: Long) {
            suspendCoroutine<Unit> { cont ->
                Timer("Suspend Timer", false).schedule(timeMillis) {
                    cont.resume(Unit)
                }
            }
        }

        private val threads: MutableList<Job> = mutableListOf()

        internal fun newThread(tw: ThreadWrapper) {
            val job = tw.thread
            threads.add(job)
        }

        internal fun cancelAll() {
            threads.forEach {
                it.cancel(CancellationException("Stopped by ThreadWrapper"))
            }
            threads.clear()
        }
    }
}

现在,我将这样编写JS代码:

new ThreadWrapper(function(continuation) {
    Thread.sleep(2000, continuation);
    print('Hello from module1!');
});

不幸的是,这不起作用。我确实看到了打印语句,但是它立即发生,忽略了睡眠调用。我对暂停函数的理解是,它们只是将延续作为第二个参数,仅此而已。我要将延续性传递给javascript函数,因此我应该能够使用该延续性调用暂停的函数,不是吗?

起初我以为是因为我从未真正在suspendCoroutine调用中恢复协程。如果将callActualMethod行移到suspendCoroutine块的外部,并在块调用cont.resume(Unit)的内部,则会得到一个IllegalStateException,指出协程已经恢复,这并没有多大用处也有感觉。

我也读过关于continuation interceptors的内容,但是这些内容似乎相当先进。我不确定为什么在我的方法中需要这些。

任何帮助将不胜感激,谢谢!

0 个答案:

没有答案