Java之wait()和notify()实例讲解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QQB67G8COM/article/details/89647969

Object对象的wait()和notify():
wait:导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法,该方法是会释放锁的。
notify:唤醒正在等待对象监视器的单个线程。 如果任何线程正在等待这个对象,其中一个被选择被唤醒。 选择是任意的,并且由实施的判断发生。 线程通过调用wait方法之一等待对象的监视器。
该方法不释放锁的。
wait和notify必须配合synchronized使用,而且wait必须在notify前用,wait后就会进入notify所在的线程,notify后唤醒wait所在的线程,但是wait所在的线程仍然没有获取锁,需要等待notify所在的线程释放锁。

代码示例:

public class WNDemo {
	private volatile static List<String> list = new ArrayList<>(20);
	
	public void add() {
		list.add("ljj");
	}
	
	public int size() {
		return list.size();
	}
	
	public static void main(String[] args) {
		final WNDemo wDemo = new WNDemo();
		final Object lock = new Object();
		
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					synchronized(lock) {
						System.out.println("已进入t1");
						for(int i = 0; i < 10; ++i) {
							wDemo.add();
							System.out.println("当前的线程:"+Thread.currentThread().getName()+"添加了一个元素。。");
							Thread.sleep(200);
							if (wDemo.size() == 5) {
								lock.notify();
								System.out.println("已发出通知!");
							}
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "t1");
		
		Thread t2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
					synchronized(lock) {
						System.out.println("已进入t2");
						if (wDemo.size() != 5) {
							try {
								System.out.println("t2释放锁前");
								lock.wait();
								System.out.println("t2释放锁后");
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						System.out.println("t2线程收到通知");
						throw new RuntimeException();
					}
			}
		}, "t2");
		t2.start();
		t1.start();
	}
}

解析:
t2线程先启动并先获得锁,并执行wait()后释放锁进入阻塞状态。
t1线程获得锁,循环到5时就发出通知,但没有释放锁,直到释放锁后t2才能继续执行。
缺点:通讯延时

利用java.util.concurrent包的CountDownLatch来实现实时通讯:
代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class WNDemo {
	private volatile static List<String> list = new ArrayList<>(20);
	
	public void add() {
		list.add("ljj");
	}
	
	public int size() {
		return list.size();
	}
	
	public static void main(String[] args) {
		final WNDemo wDemo = new WNDemo();
		final CountDownLatch cLatch = new CountDownLatch(1);//发出一次通知
		
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					System.out.println("已进入t1");
					for(int i = 0; i < 10; ++i) {
						wDemo.add();
						System.out.println("当前的线程:"+Thread.currentThread().getName()+"添加了一个元素。。");
						Thread.sleep(200);
						if (wDemo.size() == 5) {
							cLatch.countDown();
							System.out.println("已发出通知!");
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "t1");
		
		Thread t2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				System.out.println("已进入t2");
				if (wDemo.size() != 5) {
					try {
						System.out.println("t2释放锁前");
						cLatch.await();
						System.out.println("t2释放锁后");
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("t2线程收到通知");
				throw new RuntimeException();
			}
		}, "t2");
		t2.start();
		t1.start();
	}
}

猜你喜欢

转载自blog.csdn.net/QQB67G8COM/article/details/89647969