Androidで kotlinx.coroutines の channel の動作確認をした

# 参考

- https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
- https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md

# Channelの基本

### Channelの種類

クラス名 | 説明
--------|------
Channel | Channelのレシーバーが一つの場合に使用する。
BroadcastChannel | Channelのレシーバーが複数存在する場合に使用する。

### Channelの要素を追加する方法

メソッド名 | 説明
--------|-------
send() | 
offer() | suspendファンクション外で要素を追加する。

### Channelの要素を消費する方法

メソッド名 | 説明
--------|-------
receive() | 
select式 | https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#select-expression
consumeEach() | https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#building-channel-producers

# 動作確認コード

```kotlin


class MainActivity : AppCompatActivity(), AnkoLogger {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        test1()
        test2()
        test3()
        test3a()
        test4()
        test4a()
        test5()
        test5a()
    }

    /**
     * receive()の後にsend()を呼び出した場合
     *
     * 実行ログ: 無し(receiveでブロックされるため、channel1.sendまで処理が進まない。)
     */
    private fun test1() {
        val channel = Channel<Int>()
        launch(UI) {
            val result = channel.receive()
            info("test1: ${result}")
            channel.send(1)
        }
    }

    /**
     * receive()とsend()を別のコルーチンで実行した場合
     *
     * 実行ログ:
     *   test2: 1
     */
    private fun test2() {
        val channel = Channel<Int>()
        launch(UI) {
            val result = channel.receive()
            info("test2: ${result}")
        }

        launch(UI) {
            channel.send(1)
        }
    }

    /**
     * 複数のコルーチンで一つのchannelをreceive()した場合
     *
     * 実行ログ:
     *   test3-1: 1
     *   test3-2: 2
     */
    private fun test3() {
        val channel = Channel<Int>()
        launch(UI) {
            val result = channel.receive()
            info("test3-1: ${result}")
        }

        launch(UI) {
            val result = channel.receive()
            info("test3-2: ${result}")
        }

        launch(UI) {
            channel.send(1)
            channel.send(2)
            channel.send(3)
        }
    }

    /**
     * test3をBroadcastChannelにした場合
     *
     * 実行ログ:
     *   test3a-1: 1
     *   test3a-2: 1
     */
    private fun test3a() {
        val channel = BroadcastChannel<Int>(10)
        launch(UI) {
            val result = channel.openSubscription().receive()
            info("test3a-1: ${result}")
        }

        launch(UI) {
            val result = channel.openSubscription().receive()
            info("test3a-2: ${result}")
        }

        launch(UI) {
            channel.send(1)
            channel.send(2)
        }
    }

    /**
     * 複数のコルーチンで一つのchannelをselectした場合
     *
     * 実行ログ:
     *   test4-1: 1
     *   test4-2: 2
     */
    private fun test4() {
        val channel = Channel<Int>()
        launch(UI) {
            select<Unit> {
                channel.onReceive { value ->  // this is the first select clause
                    info("test4-1: ${value}")
                }
            }
        }

        launch(UI) {
            select<Unit> {
                channel.onReceive { value ->
                    info("test4-2: ${value}")
                }
            }
        }

        launch(UI) {
            channel.send(1)
            channel.send(2)
        }
    }

    /**
     * test4をBroadcastChannelにした場合
     *
     * 実行ログ:
     *   test4a-1: 1
     *   test4a-2: 1
     */
    private fun test4a() {
        val channel = BroadcastChannel<Int>(10)

        launch(UI) {
            select<Unit> {
                channel.openSubscription().onReceive { value ->
                    info("test4a-1: ${value}")
                }
            }
        }

        launch(UI) {
            select<Unit> {
                channel.openSubscription().onReceive { value ->
                    info("test4a-2: ${value}")
                }
            }
        }

        launch(UI) {
            channel.send(1)
            channel.send(2)
        }
    }

    /**
     * 複数のコルーチンで一つの channel を consumeEach した場合
     *
     * 実行ログ:
     *   test5-1: 1
     *   test5-2: 2
     */
    private fun test5() {
        val channel = Channel<Int>()
        launch(UI) {
            channel.consumeEach {
                info("test5-1: ${it}")
            }
        }

        launch(UI) {
            channel.consumeEach {
                info("test5-2: ${it}")
            }
        }

        launch(UI) {
            channel.send(1)
            channel.send(2)
        }
    }

    /**
     * test5をBroadcastChannelにした場合
     *
     * 実行ログ:
     *   test5a-1: 1
     *   test5a-1: 2
     *   test5a-2: 1
     *   test5a-2: 2
     */
    private fun test5a() {
        val channel = BroadcastChannel<Int>(10)
        launch(UI) {
            channel.consumeEach {
                info("test5a-1: ${it}")
            }
        }

        launch(UI) {
            channel.consumeEach {
                info("test5a-2: ${it}")
            }
        }

        launch(UI) {
            channel.send(1)
            channel.send(2)
        }
    }
}

```