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 synchronizedvoid 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();
}
}
}
最後更新:2017-04-03 08:26:22