Можно ли использовать Project Loom из Котлина?
Я только начинаю играть с Project Loom ...
Учитывая код Java, который, кажется, работает правильно
try (ExecutorService executor = Executors.newVirtualThreadExecutor()) {
IntStream.range(0, 16).forEach(i -> {
System.out.println("i = " + i + ", Thread ID = " + Thread.currentThread());
executor.submit(() -> {
var thread = Thread.currentThread();
System.out.println("Thread ID = " + thread);
});
});
}
Когда IntelliJ преобразует это в Kotlin, я получаю
Executors.newVirtualThreadExecutor().use { executor ->
IntStream.range(0, 16).forEach(IntConsumer { i: Int ->
println("i = $i, Thread ID = ${Thread.currentThread()}")
executor.submit(Runnable {
println("Thread ID = ${Thread.currentThread()}")
})
})
}
private fun ExecutorService.use(block: (ExecutorService) -> Unit) {
который, кажется, компилируется нормально, но при выполнении ничего не печатается на консоли?
Есть ли какая-то скрытая несовместимость между Kotlin и Project Loom?
Дальнейшие эксперименты показывают, что
Executors.newVirtualThreadExecutor()
.submit(Runnable { println("Thread = ${Thread.currentThread()}") })
ничего не печатает, но
Executors.newCachedThreadPool()
.submit(Runnable { println("Thread = ${Thread.currentThread()}") })
выводит ожидаемый результат, поэтому между Kotlin и VirtualThreads есть что-то принципиально несовместимое. Тем не мение,
Executors.newCachedThreadPool().use { executor ->
IntStream.range(0, 16).forEach(IntConsumer { i: Int ->
println("i = $i, Thread ID = ${Thread.currentThread()}")
executor.submit(Runnable {
println("Thread ID = ${Thread.currentThread()}")
})
})
}
ничего не печатает, поэтому есть и другие проблемы ...
Executors.newCachedThreadPool().use { executor ->
IntStream.range(0, 16).forEach(IntConsumer { i: Int ->
println("i = $i, Thread ID = ${Thread.currentThread()}")
})
}
ничего не печатает, но
IntStream.range(0, 16).forEach(IntConsumer { i: Int ->
println("i = $i, Thread ID = ${Thread.currentThread()}")
})
печатает ожидаемые результаты? Также,
IntStream.range(0, 16).forEach(IntConsumer { i: Int ->
println("i = $i, Thread ID = ${Thread.currentThread()}")
executor.submit(Runnable {
println("Thread ID = ${Thread.currentThread()}")
})
})
печатает ожидаемые результаты, поэтому есть некоторая странность с
use
?
Это вызывает вопросы
- Есть ли проблемы с разработкой / реализацией Project Loom, которые вызывают проблемы для Kotlin?
- Есть ли проблемы с JDK-18, несовместимым с Kotlin?
- Есть ли какие-то проблемы с тем, как разработан / реализован Kotlin, которые не могут взаимодействовать с Project Loom?
- Есть ли проблемы с Kotlin, несовместимые с JDK-18?
1 ответ
Проблема заключалась в том, что я не определял
use
расширение функционирует должным образом. Простое исправление
private fun ExecutorService.use(block: (executorService: ExecutorService) -> Unit) = block(this)
А сейчас
Executors.newVirtualThreadExecutor().use { executorService ->
IntStream.range(0, 16).forEach(IntConsumer { i: Int ->
println("i = $i, Thread ID = ${Thread.currentThread()}")
executorService.submit(Runnable {
println("Thread ID = ${Thread.currentThread()}")
})
})
}
производит вывод, аналогичный примеру Java
i = 1, Thread ID = Thread[#1,main,5,main]
i = 2, Thread ID = Thread[#1,main,5,main]
Thread ID = VirtualThread[#19]/runnable@ForkJoinPool-1-worker-1
Thread ID = VirtualThread[#20]/runnable@ForkJoinPool-1-worker-2
i = 3, Thread ID = Thread[#1,main,5,main]
Меня часто расстраивает, когда IntelliJ автоматически создает функции расширения, потому что для меня не сразу очевидно, что поместить в тело, и в этом случае я ничего не сделал, что было неправильно. Несмотря на то, что я много гуглил, я не мог легко найти код, который позволил мне найти решения, так что это было своего рода хитростью ...
В заключение, можно будет использовать Project Loom из Котлина, если вы познаете какую-то особую черную магию ... 🥳