Concurrency 按顺序运行的非预期线程
我希望输出为0 0 1 2 2。。。但是输出是01 2 3。。。01 2 3Concurrency 按顺序运行的非预期线程,concurrency,parallel-processing,kotlin,Concurrency,Parallel Processing,Kotlin,我希望输出为0 0 1 2 2。。。但是输出是01 2 3。。。01 2 3 class Runner: Thread() { override fun run() { var i = 0 while (i < 10) { println("${Thread.currentThread().name} $i") i++ } try { Threa
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()
}
类运行程序:线程(){
覆盖趣味跑(){
变量i=0
而(i<10){
println(${Thread.currentThread().name}$i)
我++
}
试一试{
线程。睡眠(100)
}捕获(e:例外){
e、 printStackTrace()
}
}
}
趣味主线(args:Array){
val-nah=Runner()
val blah=Runner()
不,开始
等等,开始
}
什么是不正确的 这个代码的输出基本上可以是两个线程编号的任何交叉版本。它们都将按顺序分别打印从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 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
<~100毫秒>
T1 12 3
T2 12 3
出局112233
T1 12 3
T2 12 3
出局112233
T1 12 3
T2 12 3
出局112233
请注意,Thread.sleep
本身也是如此,如果您在这里输入足够长的延迟,那么在大多数情况下,使用它来实现此目的都会很顺利
如果您想编写可预测运行的多线程代码,请研究不同的同步方法(
synchronized
、锁、信号量等)。好的,此代码的输出基本上可以是两个线程编号的任何交错版本。它们都将按顺序分别打印从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 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
<~100毫秒>
T1 12 3
T2 12 3
出局112233
T1 12 3
T2 12 3
出局112233
T1 12 3
T2 12 3
出局112233
请注意,Thread.sleep
本身也是如此,如果您在这里输入足够长的延迟,那么在大多数情况下,使用它来实现此目的都会很顺利
如果您想编写可预测运行的多线程代码,请查看不同的同步方法(已同步、锁、信号量等)。更改为
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()
}
}
}
}
类运行程序:线程(){
覆盖趣味跑(){
变量i=0
而(i<10){
println(${Thread.currentThread().name}$i)
我++
试一试{
线程。睡眠(100)
}捕获(e:例外){
e、 printStackTrace()
}
}
}
}
也许它离你很近,但这个结果并不总是存在
T1 1
t21
T1 2
t22
T1 3
t23
.
.
改为
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()
}
}
}
}
类运行程序:线程(){
覆盖趣味跑(){
变量i=0
而(i<10){
println(${Thread.currentThread().name}$i)
我++
试一试{
线程。睡眠(100)
}捕获(e:例外){
e、 printStackTrace()
}
}
}
}
也许它离你很近,但这个结果并不总是存在
T1 1
t21
T1 2
t22
T1 3
t23
.
.
可以线程睡眠应该在while子句中。但为什么呢?在实际系统中创建线程需要一些时间。我想我已经在前面的问题中提到过。您必须先解开“之前发生的”和线程中发生的事情。在这种情况下,您还可以使用CyclicBarrier(2)
获取预期结果。没有必要这样一个线程。在你的情况下,睡眠。好的。线程睡眠应该在while子句中。但为什么呢?在实际系统中创建线程需要一些时间。我想我已经在前面的问题中提到过。您必须先解开“之前发生的”和线程中发生的事情。在这种情况下,您还可以使用CyclicBarrier(2)
获取预期结果。在您的情况下,不需要这样的线程。sleep
。使用@Synchronized注释,输出为0 0 1 2 3 2。。。这也正确吗?Kotlin的@Synchronized
注释与Java中的Synchronized
关键字相同。这只会防止不同线程同时进入对象的方法。在这种情况下,这没有任何作用,因为您的两个线程是两个不同的对象实例。请参阅。使用@Synchronized注释,输出为0 0 1 1 2 3 2。。。这也正确吗?Kotlin的@Synchronized
注释与Java中的Synchronized
关键字相同。这只会防止不同线程同时进入对象的方法。这在这方面没有任何作用