未按顺序运行的线程

时间:2017-07-22 03:30:57

标签: concurrency parallel-processing kotlin

我预计输出为0 0 1 1 2 2 ...但输出为0 1 2 3 ... 0 1 2 3

class Runner: Thread() {
    override fun run() {
        var i = 0
        while (i < 10) {
            println("${Thread.currentThread().name} $i")
            i++
        }

        try {
            Thread.sleep(100)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

fun main(args: Array<String>) {
    val nah = Runner()
    val blah = Runner()

    nah.start()
    blah.start()
}

什么是不正确的?

2 个答案:

答案 0 :(得分:2)

嗯,这段代码的输出基本上可以是两个线程的任何交错版本。数字。它们都按顺序分别打印1到10的数字,但不能保证何时相互之间发生这种情况,因为它们之间没有同步,并且没有循环内部的延迟,他们都只是试图尽快打印数字。

这些都是此代码完全有效的结果:

T1    1   2   3
T2      1   2   3
out   1 1 2 2 3 3

T1    1 2 3
T2          1 2 3
out   1 2 3 1 2 3

T1          1 2 3
T2    1 2 3
out   1 2 3 1 2 3

T1    1   2 3
T2      1     2 3
out   1 1 2 3 2 3

如果你把延迟放在循环中,并且它已经足够长了,你会在某种程度上保证你得到像1 1 2 2 3 3这样的序列,但是它的顺序是两个副本的顺序。在线程之间打印的数字仍然取决于线程在特定运行中如何安排。

      < ~100 ms >
T1   1           2           3
T2    1           2           3
out  11          22          33

T1    1           2           3
T2   1           2           3
out  11          22          33

T1    1          2            3
T2   1            2          3
out  11          22          33

请注意Thread.sleep本身isn't perfectly accurate,并且如果你在这里投入足够长的延迟,大部分时间都会使用synchronized

如果要编写可预测运行的多线程代码,请查看不同的同步方法(DataSet ds = getDataSet(); ,锁,信号量等)。

答案 1 :(得分:0)

更改为

class Runner: Thread() {
    override fun run() {
        var i = 0
        while (i < 10) {
            println("${Thread.currentThread().name} $i")
            i++
            try {
                Thread.sleep(100)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

也许它离你很近,但这个结果并不总是存在。

  

T1 1
    T2 1
    T1 2
    T2 2
    T1 3
    T2 3
    。     。