线程Thread(JAVA) 篇六 线程间通信(wait(),notify(),notifyAll())--等待唤醒机制

线程间通信:多个线程处理同一资源,但是线程任务却不同线程间通信解释图
如图:有两辆车,一辆车往出输送煤炭,一辆车往里输送煤炭。此图可以粗略的理解为线程间通信。
多个线程:两个车如同两个线程。
同一资源:煤炭为同一资源。
任务不同:一辆车往里送煤炭,一辆车往出送煤炭。则两个线程任务不同。

/**
 * 煤炭类[同一资源]
 */
class Coal
{
	String  carName;
	String weight;
}

/**
 * 往里输送煤炭类
 */
class InputCar implements Runnable
{
	Coal coal;
	public InputCar(Coal coal)
	{
		this.coal = coal;
	}
	@Override
	public void run()
	{
		while(true)
		{
			coal.weight = "输入10吨";
			try
			{
				Thread.sleep(10);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			coal.carName = "输入车";
			System.out.println("InputCar : " + coal.carName +" ... "+coal.weight);
		}
	
	}
}

/**
 * 往外输送煤炭类
 */
class OutputCar implements Runnable
{
	Coal coal;
	public OutputCar(Coal coal)
	{
		this.coal = coal;
		
	}
	@Override
	public void run()
	{
		while(true) 
		{
			coal.carName = "输出车";
			try
			{
				Thread.sleep(10);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			coal.weight = "输出车5吨";
			System.out.println("OutputCar : 车次-" + coal.carName +" ... 碳重-"+coal.weight+"吨");
		}
	}
}
/**
 * 测试
 */
public class Test
{
	public static void main(String[] args)
	{
		Coal coal = new Coal();
		
		InputCar inputCar = new InputCar(coal);
		OutputCar outputCar = new OutputCar(coal);
		
		Thread thread = new Thread(inputCar);
		Thread thread2 = new Thread(outputCar);
		
		thread.start();
		thread2.start();
	}
}

部分结果如下:

InputCar : 输入车 … 输出车5吨
OutputCar : 车次-输入车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输出车5吨
OutputCar : 车次-输入车 … 碳重-输出车5吨吨

可以看出打印结果是有问题的,此问题的出现请参考
线程Thread(JAVA) 篇三 synchronized(同步)
线程Thread(JAVA) 篇四 synchronized(同步)
修改如下所示:

/**
 * 煤炭类[同一资源]
 */
class Coal
{
	String  carName;
	String weight;
}

/**
 * 往里输送煤炭类
 */
class InputCar implements Runnable
{
	Coal coal;
	public InputCar(Coal coal)
	{
		this.coal = coal;
	}
	@Override
	public void run()
	{
		while(true)
		{
			synchronized(coal) 
			{
				coal.weight = "输入10吨";
				try
				{
					Thread.sleep(10);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				coal.carName = "输入车";
				System.out.println("InputCar : " + coal.carName +" ... "+coal.weight);
			}
		}
	
	}
}

/**
 * 往外输送煤炭类
 */
class OutputCar implements Runnable
{
	Coal coal;
	public OutputCar(Coal coal)
	{
		this.coal = coal;
		
	}
	@Override
	public void run()
	{
		while(true) 
		{
			synchronized(coal) 
			{
				coal.carName = "输出车";
				try
				{
					Thread.sleep(10);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				coal.weight = "输出车5吨";
				System.out.println("OutputCar : 车次-" + coal.carName +" ... 碳重-"+coal.weight+"吨");
			}
		}
	}
}
/**
 * 测试
 */
public class Test
{
	public static void main(String[] args)
	{
		Coal coal = new Coal();
		
		InputCar inputCar = new InputCar(coal);
		OutputCar outputCar = new OutputCar(coal);
		
		Thread thread = new Thread(inputCar);
		Thread thread2 = new Thread(outputCar);
		
		thread.start();
		thread2.start();
	}
}

结果如下:

InputCar : 输入车 … 输入10吨
InputCar : 输入车 … 输入10吨
InputCar : 输入车 … 输入10吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨

这次的打印结果对了,但是这仅仅解决了同步问题,还没到线程间通信问题,现在想要的打印结果是输入10吨和输出5吨相间的效果,如下:

InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨

要达到这种效果,需要使用线程的等待唤醒机制,主要涉及到的方法有:
wait(); 让线程处于冻结状态,被wait的线程会被存储到线程池中。
notify() 唤醒线程池中一个任意线程。
notifyAll(); 唤醒线程池中所有的线程。
这三个方法必须定义在同步中:因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个线程上的哪个锁
修改代码如下:

/**
 * 煤炭类[同一资源]
 */
class Coal
{
	String  carName;
	String weight;
	boolean flag = true;
}

/**
 * 往里输送煤炭类
 */
class InputCar implements Runnable
{
	Coal coal;
	public InputCar(Coal coal)
	{
		this.coal = coal;
	}
	@Override
	public void run()
	{
		while(true)
		{
			synchronized(coal) 
			{
				//当标志位为 true时,输入煤炭
				if(coal.flag) 
				{
					coal.weight = "输入10吨";
					try
					{
						Thread.sleep(10);
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
					coal.carName = "输入车";
					System.out.println("InputCar : " + coal.carName +" ... "+coal.weight);
					coal.flag = false;//标志位置false
					coal.notify();//唤醒线程池中的任意一个线程
				}
				else 
				{//当标志位为 false时,输出煤炭,输入线程进入等待状态
					try
					{
						coal.wait();
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}
			}
		}
	
	}
}

/**
 * 往外输送煤炭类
 */
class OutputCar implements Runnable
{
	Coal coal;
	public OutputCar(Coal coal)
	{
		this.coal = coal;
	}
	@Override
	public void run()
	{
		while(true) 
		{
			synchronized(coal) 
			{
				//当标志位为 false时,输出煤炭
				if(!coal.flag) 
				{
					coal.carName = "输出车";
					try
					{
						Thread.sleep(10);
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
					coal.weight = "输出车5吨";
					System.out.println("OutputCar : 车次-" + coal.carName +" ... 碳重-"+coal.weight+"吨");
					coal.flag = true;//标志位置为true
					coal.notify();//唤醒线程池中的任意一个线程
				}
				else
				{//当标志位为 true时,输入煤炭,输出线程进入等待状态
					try
					{
						coal.wait();
					} catch (InterruptedException e1)
					{
						e1.printStackTrace();
					}
				}
			
			}
		}
	}
}
/**
 * 测试
 */
public class Test
{
	public static void main(String[] args)
	{
		Coal coal = new Coal();
		
		InputCar inputCar = new InputCar(coal);
		OutputCar outputCar = new OutputCar(coal);
		
		Thread thread = new Thread(inputCar);
		Thread thread2 = new Thread(outputCar);
		
		thread.start();
		thread2.start();
	}
}

输出结果如下:

InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
可见达到了预期的效果。这就是线程间的等待唤醒机制的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值