【问题标题】:Can Project Loom be used from Kotlin?可以从 Kotlin 使用 Project Loom 吗?
【发布时间】:2021-12-13 18:39:12
【问题描述】:

我刚刚开始玩 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 和虚拟线程之间存在根本不兼容的地方。然而,

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有点奇怪?

这引出了问题

  1. Project Loom 的设计/实施方式是否存在一些问题 这给 Kotlin 带来了问题?
    • JDK-18 是否存在一些不兼容的问题 使用 Kotlin?
  2. Kotlin 的设计/实现方式是否存在一些问题 无法与 Project Loom 互操作?
    • Kotlin 是否存在一些与不兼容的问题 JDK-18?

【问题讨论】:

  • 我强烈建议在直接转换的 Java 代码上使用 Kotlin 功能。
  • 你的ExecutorService.use函数里面有什么?实际上,在当前的 Loom JDK 构建中,ExecutorService 实现了 AutoCloseable,因此 Kotlin 标准库中的 use 函数应该可以正常工作。
  • 如果您将newVirtualThreadExecutor() 替换为newCachedThreadPool(),它会起作用吗?
  • @МихаилНафталь 感谢您的建议,但这并没有帮助。
  • @undermark5 - 这些是实验......重点不是使用Kotlin功能,重点是回答问题,Kotlin可以与Project Loom一起使用吗?

标签: kotlin project-loom


【解决方案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 自动创建扩展函数时,我经常感到很沮丧,因为我并不能立即明白要在主体中放入什么,而在这种情况下,我什么也没做,这是错误的。尽管在谷歌上搜索了很多,但我还是很难找到让我找到解决方案的代码,所以它有点碰巧......

结论,应该可以使用 Kotlin 的 Project Loom,一旦你知道一些特殊的黑魔法......?

【讨论】:

    猜你喜欢
    • 2022-11-09
    • 1970-01-01
    • 2020-02-01
    • 2020-10-19
    • 1970-01-01
    • 2020-12-01
    • 2018-08-10
    • 2018-02-16
    • 1970-01-01
    相关资源
    最近更新 更多