Java中的多线程(三)之线程间的通信

在第一篇文章中说过Java的并发模型是共享内存,所以线程间的通信也是基于这个原理实现的,在Java中,使用wait/notify/notifyAll是实现线程间通信的一种简单方式。

我们看下这三个方法的说明(在Object中定义)

通过说明我们看出,wait会导致当前线程进行等待,直到另外一个线程调用notify()、notifyAll()或者等待一个确定的时间过后才会停止等待状态。而notify方法的说明更加精准,它会唤醒在这个对象监视器上进行等待的单个线程。

OK,通过api的说明,我们其实就已经明白了他们的意义。需要注意的是:

1:这些线程必须与某一个对象监视器进行绑定使用,某则notify不知道去通知谁,会报异常。

2:调用wait的时候,它会释放掉对象的锁,不然的话,notify通知还有意思吗?

3:在调用wait方法时,它会抛出一个InterruptedException,条件是if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.就是说,如果当前线程在等待wait的时候被其它线程给中断掉了,它就会抛出这个异常,并且它的中断标志会被清除,这个到以后说。

好了,看完api说明一切都明白了。我们只要有一个对象锁就可以很方便的实现线程间的通信了,关于线程锁的问题,请参考上一篇文章。

eg:

public class WaitAndNotifyTest {
	public static void main(String[] args) {
		Product product = new Product();
		product.setCount(1);

		//
		Thread producerThread = new Thread(new Producer(product));
		Thread customerThread = new Thread(new Customer(product));
		producerThread.start();
		customerThread.start();
	}
}

class Product {
	private int count;

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}
}

class Producer implements Runnable {
	private Product product;

	public Producer(Product product) {
		this.product = product;
	}

	@Override
	public void run() {
		synchronized (product) {
			for (int i = 0; i < 10; i++) {
				while (product.getCount() == 1) {
					try {
						product.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("生产了一个产品");
				product.setCount(1);
				product.notify();
			}
		}
	}

}

class Customer implements Runnable {
	private Product product;

	public Customer(Product product) {
		this.product = product;
	}

	@Override
	public void run() {
		synchronized (product) {
			for (int i = 0; i < 10; i++) {
				while (product.getCount() == 0) {
					try {
						product.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("消费了一个产品");
				product.setCount(0);
				product.notify();
			}
		}
	}
}

上述代码的输出结果为:

消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
消费了一个产品
生产了一个产品
OK,总体来说,使用wait和notify还是比较简单的。它们是定义在Object上的方法,任何 对象都有,而且它必须在获得锁的情况下使用,如果在执行过程中它被任何其它线程中断,它会抛出 InterruptedException异常。

在api说明中,它给我们提供了一个比较特殊的情况,即线程有可能在没有被通知、中断或者时间超期等情况下被唤醒,因此,在判断condition是否满足情况时,我们应该使用while而不是if。

synchronized (obj) {
         while (<condition does not hold>)
             obj.wait(timeout);
         ... // Perform action appropriate to condition
     }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值