Java Kotlin CoroutineDispatcher创建额外的线程,而不是重新抛出RejectedExecutionException

Java Kotlin CoroutineDispatcher创建额外的线程,而不是重新抛出RejectedExecutionException,java,multithreading,kotlin,kotlin-coroutines,Java,Multithreading,Kotlin,Kotlin Coroutines,下面是一个例子: // max 1 pending task in queue val queue = LinkedBlockingQueue<Runnable>(1) // max 1 thread / 1 active task val executor = ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, queue) val start = System.currentTimeMillis() fun run() {

下面是一个例子:

// max 1 pending task in queue
val queue = LinkedBlockingQueue<Runnable>(1)
// max 1 thread / 1 active task 
val executor = ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, queue)

val start = System.currentTimeMillis()
fun run() {
    val millis = System.currentTimeMillis() - start
    val thread = Thread.currentThread().name
    println("executing after $millis ms on thread $thread")
    Thread.sleep(3000)
}

executor.execute { run() }
executor.execute { run() }
// executor.execute { run() } // RejectedExecutionException, ok

Thread.sleep(10_000)

val job = SupervisorJob()
val dispatcher = executor.asCoroutineDispatcher()
val exceptionHandler = CoroutineExceptionHandler { _, _ ->
    println("never invoked")
}

val scope = CoroutineScope(job + dispatcher + exceptionHandler)

scope.launch { run() }
scope.launch { run() }
scope.launch { run() } // !
//队列中最多有1个挂起的任务
val队列=LinkedBlockingQueue(1)
//最多1个线程/1个活动任务
val executor=ThreadPoolExecutor(1,1,0L,TimeUnit.ms,队列)
val start=System.currentTimeMillis()
趣味跑(){
val millis=System.currentTimeMillis()-启动
val thread=thread.currentThread().name
println(“在线程$thread上的$millis ms之后执行”)
线程。睡眠(3000)
}
executor.execute{run()}
executor.execute{run()}
//executor.execute{run()}//RejectedExecutionException,确定
线程。睡眠(10_000)
val作业=主管作业()
val dispatcher=executor.ascoroutinedpatcher()
val exceptionHandler=CoroutineExceptionHandler{{{{,}
println(“从未调用”)
}
val scope=CoroutineScope(作业+调度程序+异常处理程序)
scope.launch{run()}
scope.launch{run()}
scope.launch{run()}/!
最后一行导致创建新线程,而不是抛出
RejectedExecutionException
(或调用
exceptionHandler
):

在线程池-1-线程-1上3毫秒后执行
3006毫秒后在线程池-1-thread-1上执行
在线程池-1-thread-1上10063毫秒后执行
在线程kotlinx.coroutines.DefaultExecutor上10079毫秒后执行
在线程池-1-thread-1上13066毫秒后执行


如果队列已满,则上述代码应失败,但我认为没有办法用Kotlin协同程序正确地实现它:使用自定义的
拒绝执行处理程序
抛出不同的异常有助于实现所需的行为,但违反了
执行者
/
拒绝执行处理程序
契约,可能只会破坏其他代码。

a
Dispatcher
不是一个执行人,有着完全不同的合同和目的。特别是,不能不发送一个协同程序的恢复

与Java线程类似,它相当于
Thread.destroy()
,这会使线程消失而不留痕迹。没有
最后执行
块,没有
同步
块退出,因为线程没有经历任何使其完成的异常
Thread.destroy()
从Java中删除有一个很好的理由

请注意,没有用户代码可以将
RejectedExecutionException
抛出。您有一个非常狭隘的特例,在这个特例中,协程根本不暂停,它们只是开始。这是您将任务提交类比为合理的唯一原因