多執行緒之兩個執行緒交替列印的問題分析

2022-07-24 08:54:10 字數 3105 閱讀 9417

場景一

在我們面試中經常會有這麼乙個場景,就是我們用執行緒a輸出「a」字元,有執行緒b輸出「b」字元,交替進行,要求a執行緒執行完任務輸出:「a執行緒列印完了」,b執行緒執行完任務輸入:「b執行緒列印完了」,最後有主線程輸出一句話「我列印完了」!

當你看到這個場景時,有點多執行緒經驗的人肯定會感覺很容易,然後有可能進行下面的實現,上**:

//

a執行緒類

public

class threada extends

thread

@override

public

void

run()

system.out.println("a執行緒列印完了");

}}//

b執行緒類

public

class threadb extends

thread

@override

public

void

run()

system.out.println("b執行緒列印完了");

}}//

測試類public

class

testthread

catch

(interruptedexception e)

system.out.println("交替列印完成");

}public

synchronized

void

printstr(string str)

else

if("b".equals(str))

try

catch

(interruptedexception e) }}

上面的**猛一看很完美,但是如果你真正執行過之後你會發現出現下面的結果,「a」和「b」字元是交替列印了,但是我們想要的三句話,只輸出了一句,並且你的idea一直處在執行狀態:

其實如果我們仔細分析**就不難發現為什麼程式一直處在沒有結束執行的狀態,並且只列印了一句話而不是三句話:再出去最後乙個threadb-----b的時候結合**你會發現這是執行緒b會執行nofity喚醒a執行緒,然後自己進入wait狀態,a執行緒被喚醒後執行a執行緒的run方法,但是現在a執行緒中的run方法的for已經執行晚了,也就是沒法進入for迴圈體了,所以就直接執行了列印語句,這也就是最後一行列印的原因,而因為a執行緒沒有進入for迴圈體,所以沒有呼叫同步方法printstr,也就沒有辦法呼叫裡面的notify來喚醒b執行緒,那麼b執行緒也就沒有辦法執行列印語句了,一直處在wait狀態,也就是b執行緒一致處在沒有結束的狀態,那自然而然主線程也不會輸出列印語句。

還記得我們在上面的**中說的乙個執行緒優先順序的問題嗎?如果你對這段**執行多次的情況你會發現,第一次列印的可不都是「a」字元,還有可能是「b」,這是為什麼呢?

其實這主要使我們對執行緒優先順序理解的乙個誤區,對於執行緒優先順序我們通常的理解是具有較高優先順序的執行緒會優先執行,其實這句話的理解應該是,在多執行緒競爭資源時具有較高優先順序的執行緒會有更大的概率獲取資源,也就是說並不是每次都是它先獲取資源,而是在大量多次的資源競爭中,它獲取到資源的次數會比低優先順序的執行緒多。

其實只需要**稍微改動就可以解決問題,看**:

//

a執行緒類

public

class threada extends

thread

@override

public

void

run()

system.out.println("a執行緒列印完了");

}}//

b執行緒類

public

class threadb extends

thread

@override

public

void

run()

system.out.println("b執行緒列印完了");

}}//

測試類public

class

testthread

catch

(interruptedexception e)

system.out.println("交替列印完成");

}public

synchronized

void printstr(int

count,string str)

else

if("b".equals(str))

try }

catch

(interruptedexception e) }}

場景二因為我們上面的交替輸出的場景過於簡單,我們稍微改變一下,變成對乙個字串'adasdfsafwfvgs'兩個執行緒交替輸出字元,最後要求a執行緒執行完任務輸出:「a執行緒列印完了」,b執行緒執行完任務輸入:「b執行緒列印完了」,最後有主線程輸出一句話「我列印完了」!

@data

public

class

testthread

public

class threadb extends

thread

}system.out.println("b執行緒列印完了");}}

public

class threada extends

thread

}system.out.println("a執行緒列印完了");}}

}

測試類:

@runwith(springrunner.class))

public

class

testthreadtest

catch

(interruptedexception e)

system.out.println("我列印完了");}}

測試結果:

多執行緒交替列印解決方案

多執行緒技術 兩個執行緒交替列印奇數和偶數

1.要列印的資源 1 package com.mytest.thread 2 3 4 要列印的資源 5 6 7 public class num 2.列印奇數的執行緒 1 package com.mytest.thread 2 3 public class printodd implements r...

兩個執行緒交替列印0 100的即偶數

兩個執行緒交替列印0 100的寄偶數,用wait和notify public class waitnotifyprintoddevenwait 1.拿到鎖,我們就列印 2。一旦列印完喚醒其他執行緒就休眠 static class turningrunner implements runnable c...

兩個執行緒交替列印數字 Condition喚醒與等待

b 看到一道關於多執行緒題 如何實現兩個執行緒交替列印數字0 9?b 首先我們會想到要實現交替列印,那麼就要其中乙個執行的時候,另外乙個處於等待狀態,當該執行緒執行完的時候,喚醒另外乙個。如此執行就可實現。我們可以通過wait和notify對執行緒進行狀態控制,並且我們需要兩個監視器分別對這兩個執行...