我必须编写一段代码,创建两个线程 - S 和 W。线程 S 以 1000 毫秒的延迟执行从 true 到 false 的切换。线程 W 正在等待线程 S 的“true”,并以 100ms 的延迟从 30 秒开始倒计时输出到控制台,并在线程 S 切换回 false 时暂停其操作。 线程运行终止的条件是倒计时达到 0 秒。
首先,我创建了两个类 - ThreadW 和 ThreadS。 在 ThreadS 中,我创建了 true 和 false 之间的状态切换
ThreadS.kt
class ThreadS() : Thread() {
override fun run()
{
var isTrue:Boolean = true
while (true)
{
if (isTrue)
{
Thread.sleep(1000)
isTrue = false
println(isTrue)
}
else
{
Thread.sleep(1000)
isTrue = true
println(isTrue)
}
}
}
}
在主文件中,我创建了协程并创建了 ThreadS 的类实例,然后启动它
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
var t2 = ThreadW()
t2.start()
}
问题是我必须将切换器的值转移到另一个线程,并且不知道如何正确执行。 我曾试图通过渠道解决这个问题,但我的尝试没有成功。 这是 ThreadW 文件的代码,我尝试通过渠道解决它
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
class ThreadW() : Thread() {
override fun run() {
val a = runBlocking {
var timer : Int = 30
var t1 = ThreadS()
val channel = Channel<Boolean>()
launch { t1.start() }
val dataFromChannel = channel.receive()
println(dataFromChannel)
println("Done")
if (dataFromChannel == true)
{
Thread.sleep(100)
timer -= 1
}
println(timer)
}
}
}
在我看来,
isTrue
和 timer
变量应该在两个线程之间共享并存在于它们之外。您应该解决的经典问题是可能的竞争条件,当一个线程更新变量而另一个线程同时读取该值时,会导致获得stale值。
有多种方法可以防止竞争情况。在这种情况下,使用
Atomic
似乎是最简单的解决方案。
val isTrue = AtomicBoolean(true)
val timer = AtomicInteger(30)
原子类型保证每次读/写操作都发生在单条指令中,并且不会与中间的值发生交互。
fun main() {
val isTrue = AtomicBoolean(true)
val timer = AtomicInteger(30)
val threadW = thread {
while (timer.get() != 0) {
println("ThreadW runs")
if (isTrue.get()) {
println("Timer: $timer")
Thread.sleep(100L)
timer.getAndDecrement()
}
}
}
val threadS = thread {
while (timer.get() != 0) {
println("ThreadS runs")
if (isTrue.get()) {
println("isTrue = true. Sleeping...")
Thread.sleep(1000L)
isTrue.set(false)
println("Set to false")
} else {
println("isTrue = false. Sleeping...")
Thread.sleep(1000L)
isTrue.set(true)
println("Set to true")
}
}
}
}
您也可以使用协程来完成此操作,只需将
thread
替换为 launch()
:
fun main() {
val isTrue = AtomicBoolean(true)
val timer = AtomicInteger(30)
val threadW = launch(Dispatchers.Default) {
while (timer.get() != 0) {
println("ThreadW runs")
if (isTrue.get()) {
println("Timer: $timer")
delay(100L) // Note that instead of Thread.sleep() coroutines use delay()
timer.getAndDecrement()
}
}
}
val threadS = launch(Dispatchers.Default) {
...
}
}