Инициализация многопоточных массивов в Котлине

Скажем, у меня есть следующие функции, которые позволяют мне создавать матрицы:

inline fun <reified T> Matrix2D(w: Int, h: Int, init: (Int, Int) -> T) = Array(w){ x -> Array(h){ y -> init(x, y) } } inline fun <reified T> Matrix2D(w: Int, h: Int, value: T) = Array(w){ Array(h){ value } } // For example: val m = Matrix2D(400, 400) { x, y -> Color(x.toDouble() / 400.0, y.toDouble() / 400.0, 0.0) } 

Я также не хочу допускать nullability, потому что это будет боль, чтобы иметь дело с доступом к элементу позже.

Как бы я инициализировал такую ​​матрицу, используя несколько потоков / сопрограмм, где каждый из них инициализирует свою собственную плиту матрицы, не допуская нулеуточности матричных ячеек?

Да, вы можете создать Matrix2D параллельно, например:

 val threads = Matrix2D(10, 3){x, y-> Thread.currentThread() }.flatten().distinct() // v--- size > 1 println(threads.size) 

 inline fun <reified T> Matrix2D(w: Int, h: Int, crossinline init: (Int, Int) -> T)= // v--- create array in parallel generatorOf(w){x -> Array(h) {y -> init(x, y) } }.map{ it() }.toTypedArray() // get the final result `Matrix2D` ---^ // v--- create array generator inline fun <reified T> generatorOf(size: Int, crossinline init:(Int) -> T) = //v--- you can use `ForkJoinPool#commonPool`, but it will run task in work thread ForkJoinPool(20).let { Array(size) { i -> it.submit(Callable { init(i) }).let { { it.get() } } } // return the lambda generator ()->T ---^ } 

Вы также можете написать функцию расширения toArray чтобы удалить операцию средней map и повысить производительность, например:

 inline fun <reified T> Matrix2D(w: Int, h: Int, crossinline init: (Int, Int) -> T)= // v--- init array elements in parallel generatorOf(w) { x -> Array(h) { y -> init(x, y) } }.toArray{it()} // transform to the `Matrix2D` directly ---^ // v--- convert Array<T> to Array<R> inline fun <T,reified R> Array<T>.toArray(transform:(T)->R):Array<R>{ return Array(size){i->transform(get(i))} } 

Почему Matrix2D запускает потоки в инициализации внешнего массива, вы можете увидеть сумму два double [] [] с параллельным потоком, как дальше.