java.util.concurrent包(3)——線程間通信wait/notify和await/signal

一、線程如何停止

使用stop()不安全。它會解除由線程獲取的所有鎖定,而且如果對象處於一種不連貫狀態,那麼其他線程能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。suspend()方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應該使用suspend()。正確的做法是而應在自己的Thread類中置入一個標誌,指出線程應該活動還是掛起。若標誌指出線程應該掛起,便用wait()命其進入等待狀態。若標誌指出線程應當恢復,則用一個notify()重新啓動線程。jdk1.5後提供了condition對象,這個對象的await()和singal()方法也可以達到線程通信的效果。


二、wait和notify實例

子線程循環10次,主線程循環100次。接着子線程循環10次,主線程循環100次。如此循環50次。摘自張孝祥老師線程視頻源碼。

public class TraditionalThreadCommunication

{

public static void main(String[] args)

{

final Business business = new Business();

new Thread(new Runnable() {

public void run()

{

for (int i = 1; i <= 50; i++)

{

business.sub(i);

}

}

}).start();

for (int i = 1; i <= 50; i++)

{

business.main(i);

}

}

}

class Business

{

private boolean bShouldSub = true;

public synchronized void sub(int i)

{

while (!bShouldSub)

{

try

{

this.wait();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 10; j++)

{

System.out.println("sub thread sequence of " + j + ",loop of " + i);

}

bShouldSub = false;

this.notify();

}


public synchronized void main(int i)

{

while (bShouldSub)

{

try

{

this.wait();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 100; j++)

{

System.out.println("main thread sequence of " + j + ",loop of " + i);

}

bShouldSub = true;

this.notify();

}

}


三、Condition實例

public class Condition1Test

{

public static void main(String[] args)

{

final BusinessLock business = new BusinessLock();

new Thread(new Runnable() {

public void run()

{

for (int i = 1; i <= 50; i++)

{

business.sub(i);

}

}

}).start();

for (int i = 1; i <= 50; i++)

{

business.main(i);

}

}

}

class BusinessLock

{

private boolean bShouldSub = true;

ReentrantLock lock = new ReentrantLock();

Condition condition = lock.newCondition();


public void sub(int i)

{

lock.lock();

try

{

while (!bShouldSub)

{

try

{

condition.await();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 10; j++)

{

System.out.println("sub thread sequence of " + j + ",loop of " + i);

}

bShouldSub = false;

condition.signal();

}

finally

{

lock.unlock();

}

}


public void main(int i)

{

lock.lock();

try

{

while (bShouldSub)

{

try

{

condition.await();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 100; j++)

{

System.out.println("main thread sequence of " + j + ",loop of " + i);

}

bShouldSub = true;

condition.signal();

}

finally

{

lock.unlock();

}

}

}


四、Condition實例擴展

三個線程相互通信,main循環100次,sub2循環10次,sub3循環10次。接着main循環100次,sub2循環10次,sub3循環10次。如此循環50次。

public class Condition2Test

{

public static void main(String[] args)

{

final BusinessLock2 business = new BusinessLock2();

new Thread(new Runnable() {

public void run()

{

for (int i = 1; i <= 50; i++)

{

business.main(i);

}

}

}).start();


new Thread(new Runnable() {

public void run()

{

for (int i = 1; i <= 50; i++)

{

business.sub2(i);

}

}

}).start();


new Thread(new Runnable() {

public void run()

{

for (int i = 1; i <= 50; i++)

{

business.sub3(i);

}

}

}).start();

}

}


class BusinessLock2

{

private int bShouldSub = 1;

ReentrantLock lock = new ReentrantLock();

Condition condition1 = lock.newCondition();

Condition condition2 = lock.newCondition();

Condition condition3 = lock.newCondition();


public void main(int i)

{

lock.lock();

try

{

while (bShouldSub != 1)

{

try

{

condition1.await();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 100; j++)

{

System.out.println("main thread sequence of " + j + ",loop of " + i);

}

bShouldSub = 2;

condition2.signal();

}

finally

{

lock.unlock();

}

}


public void sub2(int i)

{

lock.lock();

try

{

while (bShouldSub != 2)

{

try

{

condition2.await();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 10; j++)

{

System.out.println("sub2 thread sequence of " + j + ",loop of " + i);

}

bShouldSub = 3;

condition3.signal();

}

finally

{

lock.unlock();

}

}


public void sub3(int i)

{

lock.lock();

try

{

while (bShouldSub != 3)

{

try

{

condition3.await();

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

for (int j = 1; j <= 10; j++)

{

System.out.println("sub3 thread sequence of " + j + ",loop of " + i);

}

bShouldSub = 1;

condition1.signal();

}

finally

{

lock.unlock();

}

}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章