Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的协同程序异步只在runBlocking中工作?_Java_Kotlin_Kotlin Coroutines - Fatal编程技术网

Java 为什么我的协同程序异步只在runBlocking中工作?

Java 为什么我的协同程序异步只在runBlocking中工作?,java,kotlin,kotlin-coroutines,Java,Kotlin,Kotlin Coroutines,我正在努力理解协同程序,似乎比预期的要难理解,也许有人能给我正确的方法 我希望有一个端点(简单的helloworld)来调用一个挂起的函数 为此,我做了以下几点: @GET @Path("/test") suspend fun test() : String { coroutineScope { async { doSomething() }.await() } return "Hello" } 在doSometh

我正在努力理解协同程序,似乎比预期的要难理解,也许有人能给我正确的方法

我希望有一个端点(简单的helloworld)来调用一个挂起的函数

为此,我做了以下几点:

@GET
@Path("/test")
suspend fun test() : String {
    coroutineScope {
        async {
            doSomething()
        }.await()
    }
    return "Hello"
}
在doSomething()中,我做的很简单

private fun doSomething(){
   logger.info("request")
}
看起来很简单,而且很直截了当,阅读异步需要一个协程作用域,所以在我的代码中应该可以工作

但当我调用我的方法时,我得到:

! kotlin.KotlinNullPointerException: null
! at kotlin.coroutines.jvm.internal.ContinuationImpl.getContext(ContinuationImpl.kt:105)
! at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:179)
NPE在这上面

 public override val context: CoroutineContext
        get() = _context!!
移动
coroutineScope
进行
runBlocking
时,它会工作。知道我错过了什么吗?我怎样才能做到这一点?(我试图避免使用
GlobalScope.async


我使用dropwizard作为框架

不要将控制器功能设为挂起功能。只能从其他挂起函数或协同例程调用它们

我不知道您的端点是如何准确无误地构建的,但由于它是执行的,因此内部没有协程上下文,因为我们没有定义任何协程上下文!这就是为什么你会得到上下文的NPE

顺便说一句:下面的代码不会有异步行为,因为您会立即等待-就像正常的顺序代码一样:

async {
    doSomething()
}.await()

为了快速解决您的问题,下面我将如何重写它:

@GET
@Path("/test")
fun test() : String {
    GlobalScope.launch { // Starts "fire-and-forget" coroutine
       doSomething() // It will execute this in separate coroutine 
    }
    return "Hello" // will be returned almost immediately 
}
要了解更多有关上下文的信息,请阅读TLDR:使用Kotlin的构建器和函数创建类似于
runBlocking的上下文

@GET
@Path("/test")
fun test() : String = runBlocking {
    val deferredResult1 = async { doSomething() } // Starts immediately in separate coroutine
    val deferredResult2 = async { doSomethingElse() } // Starts immediately in separate coroutine

    logger.print("We got:${deferredResult1 .await()} and ${deferredResult2 .await()}")

    "Hello" // return value - when both async coroutines finished
}

编辑

为了避免使用
GlobalScope.
函数,我们可以使用
runBlocking

@GET
@Path("/test")
fun test() : String = runBlocking {
    val deferredResult1 = async { doSomething() } // Starts immediately in separate coroutine
    val deferredResult2 = async { doSomethingElse() } // Starts immediately in separate coroutine

    logger.print("We got:${deferredResult1 .await()} and ${deferredResult2 .await()}")

    "Hello" // return value - when both async coroutines finished
}

感谢您的回复,有什么方法可以避免使用GlobalScope吗?添加了另一个解决方案-稍微扩展以使情况变得现实