1. 程式人生 > >java.util.concurrent包(3)-執行緒間通訊wait/notify和await/signal

java.util.concurrent包(3)-執行緒間通訊wait/notify和await/signal

1 wait和notify

當呼叫wait()方法時執行緒會放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件呼叫notify()方法後本執行緒才進入物件鎖定池準備

Object的方法:void notify(): 喚醒一個正在等待該物件的執行緒。void notifyAll(): 喚醒所有正在等待該物件的執行緒。notifyAll使所有原來在該物件上等待被notify的執行緒統統退出wait狀態,變成等待該物件上的鎖,一旦該物件被解鎖,它們會去競爭。notify只是選擇一個wait狀態執行緒進行通知,並使它獲得該物件上的鎖,但不驚動其它同樣在等待被該物件notify的執行緒們,當第一個執行緒執行完畢以後釋放物件上的鎖,此時如果該物件沒有再次使用notify語句,即便該物件已經空閒,其他wait狀態等待的執行緒由於沒有得到該物件的通知,繼續處在wait狀態,直到這個物件發出一個notify或notifyAll,它們等待的是被notify或notifyAll,而不是鎖

2 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();
	}
}

3 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();
		}
	}
}

4 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();
		}
	}
}