Home > Enterprise >  How to convert Java Threads to Kotlin coroutines?
How to convert Java Threads to Kotlin coroutines?

Time:04-12

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?

CodePudding user response:

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.
  • Related