如何将Java线程转换为Kotlin Coroutines?

发布于 2025-01-20 08:41:53 字数 530 浏览 3 评论 0原文

我有一段“丑陋”的 Java 代码,需要转换为 Kotlin 惯用的协程,但我不太清楚如何转换。

Thread[] pool=new Thread[2*Runtime.getRuntime().availableProcessors()];
        for (int i=0;i<pool.length;i++)
            pool[i]=new Thread(){
                public void run() {
                    int y; while((y=yCt.getAndIncrement())<out.length) putLine(y,out[y]);
                }
            };
        for (Thread t:pool) t.start();
        for (Thread t:pool) t.join();

我认为可以使用 runBlocking 来实现,但是如何处理 availableProcessors 计数?

I have this "ugly" Java code I need to convert to Kotlin idiomatic coroutines and I cant quite figure out how.

Thread[] pool=new Thread[2*Runtime.getRuntime().availableProcessors()];
        for (int i=0;i<pool.length;i++)
            pool[i]=new Thread(){
                public void run() {
                    int y; while((y=yCt.getAndIncrement())<out.length) putLine(y,out[y]);
                }
            };
        for (Thread t:pool) t.start();
        for (Thread t:pool) t.join();

I think it is possible to implement using runBlocking but how do I deal with availableProcessors count?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

桃酥萝莉 2025-01-27 08:41:53

我将在此处做一些假设:

  1. putline()是CPU密集型而不是IO操作。我认为这是因为它使用2 * CPU内核的线程执行,通常用于CPU密集型任务。
  2. 我们只需要为out中的每个项目执行putline()。从上面的代码中,尚不清楚eg yct最初是0
  3. OUT不像数百万个项目那样大。
  4. 您不会在Kotlin中寻找1:1相同的代码,而是相同的代码。

然后,解决方案真的很容易:

coroutineScope {
    out.forEachIndexed { index, item ->
        launch(Dispatchers.Default) { putLine(index, item) }
    }
}

几个解释的单词:

  • deptagter.default coroutine dispatcher专门用于CPU计算,其线程数量取决于CPU内核的数量。我们不需要创建自己的线程,因为Coroutines提供合适的线程池。
  • 我们不会手动处理任务的队列,因为Coroutines很轻巧,我们可以根据每个项目安排一个单独的Coroutine,它们将自动排队。
  • coroutinescope()等待其孩子,因此我们不需要手动等待所有异步任务。在所有任务完成时,将执行coroutinesCope()下方的任何代码。

Java/线程与Kotlin/Coroutines代码之间的行为存在一些差异:

  • dispatchers.default默认情况下具有螺纹= CPU内核的数量,而不是2 * CPU内核。
  • 在Coroutines解决方案中,如果任何任务失败,则整个操作会引发异常。在原始代码中,错误被忽略,应用程序以不一致的状态继续。
  • 在Coroutines解决方案中,线程池与应用程序的其他组件共享。这可能是理想的行为。

I'll make some assumptions here:

  1. putLine() is a CPU intensive and not IO operation. I assume this, because it is executed using threads number of 2 * CPU cores, which is usually used for CPU intensive tasks.
  2. We just need to execute putLine() for each item in out. From the above code it is not clear if e.g. yCt is initially 0.
  3. out isn't huge like e.g. millions of items.
  4. You don't look for 1:1 the same code in Kotlin, but rather its equivalent.

Then the solution is really very easy:

coroutineScope {
    out.forEachIndexed { index, item ->
        launch(Dispatchers.Default) { putLine(index, item) }
    }
}

Few words of explanation:

  • Dispatchers.Default coroutine dispatcher is used specifically for CPU calculations and its number of threads depends on the number of CPU cores. We don't need to create our own threads, because coroutines provide a suitable thread pool.
  • We don't handle a queue of tasks manually, because coroutines are lightweight and we can instead just schedule a separate coroutine per each item - they will be queued automatically.
  • coroutineScope() waits for its children, so we don't need to also manually wait for all asynchronous tasks. Any code put below coroutineScope() will be executed when all tasks finish.

There are some differences in behavior between the Java/threads and Kotlin/coroutines code:

  • Dispatchers.Default by default has the number of threads = CPU cores, not 2 * CPU cores.
  • In coroutines solution, if any task fail, the whole operation throws an exception. In the original code, errors are ignored and the application continues with inconsistent state.
  • In coroutines solution the thread pool is shared with other components of the application. This could be a desired behavior or not.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文