JAVA多线程中synchronized,wait跟notify的关系

JAVA多线程中synchronized,wait和notify的关系
synchronized是和一个锁对象关联的,synchronized限制static方法的时候,
锁对象为这个类的class变量,相当于XXXClass.class.
synchronized限制非static方法的时候,锁对象为这个类的实例(相当于this).
synchronized限制一个对象实例的时候,如(synchronized (xlock)),锁对象为指定的这个对象实例,如xlock.
只有获得锁对象的锁的线程才能执行synchronized限制的代码.
synchronized限制static方法的时候,在某一时刻,同一个虚拟机只能有一个线程正在执行这个static方法,
因为锁对象是这个class的XXXClass.class实例,一个虚拟机只有一个XXXClass.class实例.
synchronized限制某一个类的非static方法的时候,对这个类的某一特定实例,
在某一时刻,同一个虚拟机只能有一个线程正在执行这个方法,但是可以同时执行多个实例的这个特定方法,因为锁对象不同.
wait,notify和notifyAll都只能在一个锁对象上调用,否则会发生如下异常:
java.lang.IllegalMonitorStateException: current thread not owner
下面的代码是合法的:第一个例子相当于调用了this.notifyAll();this这时候为锁对象.
public synchronized void sendNotification() throws Exception {
    notifyAll();
}

synchronized (NotifyWaitTest.lock) {
    try {
        NotifyWaitTest.lock.notifyAll();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
void notify()
唤醒在此对象监视器上等待的某一个线程.具体是哪一个可以认为是不确定的.
void notifyAll()
唤醒在此对象监视器上等待的所有线程。
void wait()
导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法.
wait会释放占有的锁,notify和notifyAll不会释放占用的锁.
下面通过一个实例代码来讲解一下:
public class NotifyWaitTest {
	public static Class lock = NotifyWaitTest.class;

	public static void main(String[] args) throws Exception {
		// new TestThread1().start();
		// new TestThread1().start();
		new TestThread2().start();
		new TestThread2().start();

		Thread.sleep(3000); 
		// NotifyWaitTest.lock.notifyAll(); //# poing 1
		synchronized (NotifyWaitTest.lock) {
			try {
				System.out.println(Thread.currentThread().getName() + " sent notification all");
				NotifyWaitTest.lock.notifyAll();

				// System.out.println(Thread.currentThread().getName() + " sent notification 1");
				// NotifyWaitTest.lock.notify();
				// System.out.println(Thread.currentThread().getName() + " sent notification 2");
				// Thread.sleep(3000);
				// NotifyWaitTest.lock.notify();
				// System.out.println(Thread.currentThread().getName() + " sent notification over");

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}

class TestThread1 extends Thread {
	public void run() {
		synchronized (NotifyWaitTest.lock) {
			try {
				System.out.println(Thread.currentThread().getName() + " wait for notification");
				NotifyWaitTest.lock.wait();

				System.out.println(Thread.currentThread().getName() + " wake up");
				for (int i = 0; i < 3; i++) {
					Thread.sleep(1000);
					System.out.println(Thread.currentThread().getName() + " doing " + i);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + " finished");
		}
	}
}

class TestThread2 extends Thread {

	public void run() {
		synchronized (NotifyWaitTest.lock) {
			System.out.println(Thread.currentThread().getName() + " wait for notification");
			try {
				NotifyWaitTest.lock.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + " wake up");
		for (int i = 0; i < 3; i++) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + " doing " + i);
		}
	}
}
在主线程里启动两个子线程,主线程和这两个线程用同一个锁对象,子线程启动后就进入
wait,主线程通过notifyAll唤醒两个子线程.
运行的结果为:
Thread-0 wait for notification
Thread-1 wait for notification
main sent notification all
Thread-0 wake up
Thread-0 doing 0
Thread-0 doing 1
Thread-0 doing 2
Thread-0 finished
Thread-1 wake up
Thread-1 doing 0
Thread-1 doing 1
Thread-1 doing 2
Thread-1 finished
*1,如果不是在synchronized关联的锁对象调用notify,notifyAll或者wait会有异常.
//NotifyWaitTest.lock.notifyAll(); //# point 1 有异常发生
*2,notifyAll会唤醒该锁对象上所有等待的线程.
*3,TestThread1中的run方法中wait之后的代码是synchronized,唤醒的两个线程是一个执行完成之后,另外一个才能执行.
*4,如果在main方法中改用下面的方式notify,在"sent notification over"之后两个子线程才会从
wait暂停的地方继续执行,因为notify并不释放锁,这时候main还占用NotifyWaitTest.lock锁对象的锁.
System.out.println(Thread.currentThread().getName() + " sent notification 1");
NotifyWaitTest.lock.notify();
System.out.println(Thread.currentThread().getName() + " sent notification 2");
Thread.sleep(3000);
NotifyWaitTest.lock.notify();            
System.out.println(Thread.currentThread().getName() + " sent notification over");
运行的结果为
Thread-0 wait for notification
Thread-1 wait for notification
main sent notification 1
main sent notification 2
main sent notification over
Thread-0 wake up
Thread-0 doing 0
Thread-0 doing 1
Thread-0 doing 2
Thread-0 finished
Thread-1 wake up
Thread-1 doing 0
Thread-1 doing 1
Thread-1 doing 2
Thread-1 finished
如果在main方法中启动的是TestThread2,因为在TestThread2的run方法中wait之后的
代码不是synchronized的,所以wakeup之后可以并行执行.
new TestThread2().start();
new TestThread2().start();
运行的结果是:
Thread-0 wait for notification
Thread-1 wait for notification
main sent notification all
Thread-0 wake up
Thread-1 wake up
Thread-0 doing 0
Thread-1 doing 0
Thread-0 doing 1
Thread-1 doing 1
Thread-0 doing 2
Thread-1 doing 2