
kotlinx.coroutines.delay()
bir askıya alma işlevidir. Mevcut iş parçacığını engellemez. Thread.sleep()
mevcut iş parçacığını engeller. Bu, bu konudaki diğer kodun şu zamana kadar yürütülmeyeceği anlamına gelir. Thread.sleep()
çıkılır.
Örnek 1 – kotlinx.coroutines.delay()
fun main(args: Array<String>) {
runBlocking {
run()
}
}
}
suspend fun run() {
coroutineScope {
val timeInMillis = measureTimeMillis {
val mainJob = launch {
//Job 0
launch {
print("A->")
delay(1000)
print("B->")
}
//Job 1
launch {
print("C->")
delay(2000)
print("D->")
}
//Job 2
launch {
print("E->")
delay(500)
print("F->")
}
//Main job
print("G->")
delay(1500)
print("H->")
}
mainJob.join()
}
val timeInSeconds =
String.format("%.1f", timeInMillis/1000f)
print("${timeInSeconds}s")
}
}
Asıl iş önce çalışacak ve sonra tarafından askıya alınacak delay()
askıya alma işlevi, ardından İş 0 -> İş 1 -> İş 2. Tüm işler askıya alınır ve aynı anda başlatılır. Daha sonra en kısa delay()
önce çalıştırılacaktır. bu timeinSeconds
tüm işleri tamamlamak için en uzun olmalıdır delay()
yani 2 saniye.
Çıktı şöyle görünür:
G->A->C->E->F->B->H->D->2.0s
Bunu anlamak oldukça kolaydır. ya değiştirirsek delay(2000)
ile birlikte Thread.Sleep(2000)
için iş1?
Örnek 2 – Dispatchers.Main üzerinde Thread.sleep()
suspend fun run() {
coroutineScope {
val timeInMillis = measureTimeMillis {
val mainJob = launch {
//Job 0
launch {
print("A->")
delay(1000)
print("B->")
}
//Job 1
launch {
print("C->")
Thread.sleep(2000)
print("D->")
}
//Job 2
launch {
print("E->")
delay(500)
print("F->")
}
//Main job
print("G->")
delay(1500)
print("H->")
}
mainJob.join()
}
val timeInSeconds =
String.format("%.1f", timeInMillis/1000f)
print("${timeInSeconds}s")
}
}
Yukarıdaki örnek 1’e benzer şekilde, Asıl iş önce çalışacak ve tarafından askıya alınacak delay()
askıya alma işlevi, ardından İş 0 İş 1. iş 0 askıya alınacaktır. Ancak, ne zaman Thread.sleep(2000)
çalıştırılıyor 1. işiş parçacığı 2 saniye süreyle bloke edilecektir. 2. iş bu sırada yürütülmez.
2 saniye sonra, D önce yazdırılacak, ardından E içinde 2. iş. 2. iş sonra askıya alınır. Çünkü Asıl iş ve iş 0 2 saniyeden daha az askıya alınırsa, hemen çalışır. iş 0 askıya alma süresi daha kısa olduğu için önce çalışacaktır.
0,5 saniye sonra, 2. iş yeniden başlatılır ve tamamlanır. yazdıracak F.
Zaman damgası #1 (0 saniyeden sonra)
- Asıl iş ve iş 0 başlatılır ve durdurulur.
- 1. iş başlatılır ve iş parçacığını engeller
Zaman Damgası #2 (2 saniye sonra)
- 1. iş yapıldı
- 2. iş başlatılır ve durdurulur.
- iş 0 ve Asıl iş yeniden başlatılır ve yapılır.
Zaman damgası #3 (0,5 saniyeden sonra)
- iş 3 yeniden başlatıldı ve bitti
Yani harcanan toplam süre yaklaşık 2,5 saniyedir.
Çıktı şöyle görünür:
G->A->C->D->E->B->H->F->2.5s
Örnek 3 – Dispatchers.Default/IO üzerinde Thread.sleep()
Bekle, ya çalıştırırsan run
kullanarak arka plan iş parçacığında işlevi askıya al Dispatchers.Default
veya Dispatchers.IO
. Örneğin:
runBlocking {
withContext(Dispatchers.Default) {
run()
}
}
Çıktı şöyle olur:
A->C->G->E->F->B->H->D->2.0s
Çıktı şuna benzer örnek 1 yukarıda, nerede Thread.sleep()
konuyu engellemiyor gibi görünüyor! Neden? Niye?
Ne zaman Dispatchers.Default
veya Dispatchers.IO
kullanıldığında, bir iş parçacığı havuzu tarafından desteklenir. her aradığımızda launch{}
farklı bir çalışan iş parçacığı oluşturulur / kullanılır.
Örneğin, kullanılan çalışan iş parçacıkları şunlardır:
- Ana iş – DefaultDispatcher-worker-1
- İş 0 – VarsayılanGönderici-işçi-2
- İş 1 – VarsayılanGönderici-işçi-3
- 2. İş – VarsayılanGönderici-işçi-4
Şu anda hangi iş parçacığının çalıştığını görmek için
println("Run ${Thread.currentThread().name}")
Yani Thread.sleep()
gerçekten o iş parçacığını engeller, ancak yalnızca DefaultDispatcher-worker-3
. Diğer işler, farklı iş parçacıklarında oldukları için çalışmaya devam edebilir.
Zaman damgası #1 (0 saniyeden sonra)
- Asıl iş, iş 0, 1. iş ve 2. iş başlatılır. Sıra rastgele olabilir. Aşağıdaki Not (1)’e bakın.
- Asıl iş, iş 0 ve iş2 askıya alınır.
- 1. iş kendi iş parçacığını engeller.
Zaman Damgası #2 (0,5 saniyeden sonra)
- 2. iş yeniden başlatılır ve yapılır.
Zaman damgası #3 (1 saniye sonra)
- iş 0 yeniden başlatıldı ve bitti
Zaman damgası #4 (1,5 saniyeden sonra)
- Asıl iş yeniden başlatıldı ve bitti
Zaman damgası #5 (2 saniye sonra)
- 1. iş yeniden başlatıldı ve bitti
Her iş farklı bir iş parçacığında çalıştığından, iş farklı zamanda başlatılabilir. Yani A, C, E, G’nin çıktısı rastgele olabilir. Böylece, işe başlama sırasının yukarıdaki Örnek 1’dekinden farklı olduğunu görüyorsunuz.
Thread.Sleep() ne zaman kullanılır?
Thread.Sleep()
neredeyse işe yaramaz çünkü çoğu zaman iş parçacığını engellemek istemiyoruz. kotlinx.coroutines.delay()
tavsiye edilir.
kişisel olarak kullanıyorum Thread.Sleep()
iş parçacığını engelleyen uzun süredir devam eden görevi simüle etmek için. Uzun süredir devam eden görevi arka plan iş parçacığına koyup koymadığımı test etmekte fayda var. Ana UI iş parçacığından çalıştırırsam, UI yanıt vermez.
bunu çağırırsam simulateBlockingThreadTask()
ana UI iş parçacığında, ana UI iş parçacığını engeller. Uygulama, yanıt vermeyen kullanıcı arayüzü ile çökecek.
private suspend fun simulateBlockingThreadTask() {
Thread.sleep(2000)
}
Ancak, iş parçacığını kullanarak arka plan iş parçacığına değiştirirsek kotlinx.coroutines.withContext()
buna sesleniyorum simulateBlockingThreadTask()
ana UI iş parçacığından uygulama çökmez.
private suspend fun simulateBlockingThreadTask() {
withContext(Dispatchers.Default) {
Thread.sleep(2000)
}
}
verim () kullanmayı unutmayın
önceki örneğimde Eşyordam Temelleri blog yazısı, kullandım yield()
kırmak için Thread.sleep()
temel olarak eşyordamın iptal edilebilir olmasına izin vermek. UI dizisini çok uzun süre engellememek genellikle iyi bir uygulamadır.
Kod örneğinde, hem bloke eden hem de bloke etmeyen iş parçacığı görevlerini simüle ediyorum. Toplam çalışma süresi 400 milisaniyedir.
private suspend fun simulateLongRunningTask() {
simulateBlockingThreadTask()
simulateNonBlockingThreadTask()
}
private suspend fun simulateBlockingThreadTask() {
repeat(10) {
Thread.sleep(20)
yield()
}
}
private suspend fun simulateNonBlockingThreadTask() {
delay(200)
}
Çözüm
Thread.sleep()
ipliği bloke eder ve kotlinx.coroutines.delay()
yapmaz.
kullanırım Thread.sleep()
uzun süredir devam eden görevi arka plan iş parçacığına düzgün bir şekilde yerleştirip yerleştirmediğimi test etmek için. Bunun dışında kullanmak istediğimiz herhangi bir sebep aklıma gelmiyor. Thread.sleep()
.