一直對線程同步的wait/notify不太理解借杰, 今天有空demo實踐了下
public class Test {
private static final Object lock = new Object();
public static void main(String[] args) {
testWaitAndNotify();
}
private static void testWaitAndNotify() {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
while (true) {
System.out.println("thread1 的run 方法-準備睡兩秒->" + System.currentTimeMillis());
try {
Thread.sleep(2000);
System.out.println("thread1 -醒了釋放鎖了-自己wait->" + System.currentTimeMillis());(1)
lock.notify();
System.out.println("thread1 -我在睡3秒后才會釋放鎖->" + System.currentTimeMillis());
Thread.sleep(3000);
lock.wait();(1)
System.out.println("thread1 被叫醒了-->" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
while (true) {
System.out.println("thread2 的run 方法-->準備睡兩秒->" + System.currentTimeMillis());
try {
Thread.sleep(2000);
// lock.wait();
System.out.println("thread2醒了釋放鎖了-自己wait-->" + System.currentTimeMillis());
lock.notify();
System.out.println("thread2 -我在睡3秒后才會釋放鎖->" + System.currentTimeMillis());
Thread.sleep(3000);
lock.wait();(2)
System.out.println("thread2 被叫醒了-->" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
thread2.start();
}
}
可以看到,thread1先拿到鎖并得到執(zhí)行进泼,然后在(1)處執(zhí)行wait讓出鎖蔗衡,然后,thread2拿到鎖乳绕,并得到執(zhí)行绞惦,并在(2)處執(zhí)行wait釋放鎖,然后需要注意的是洋措,本線程是在notify所在代碼塊執(zhí)行完畢后济蝉,才有機會競爭該把鎖
/**
* Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object.
* In other words, this method behaves exactly as if it simply
* performs the call {@code wait(0)}.
* <p>
* The current thread must own this object's monitor. The thread
* releases ownership of this monitor and waits until another thread
* notifies threads waiting on this object's monitor to wake up
* either through a call to the {@code notify} method or the
* {@code notifyAll} method. The thread then waits until it can
* re-obtain ownership of the monitor and resumes execution.
* <p>
* As in the one argument version, interrupts and spurious wakeups are
* possible, and this method should always be used in a loop:
* <pre>
* synchronized (obj) {
* while (<condition does not hold>)
* obj.wait();
* ... // Perform action appropriate to condition
* }
* </pre>
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor.
* @throws InterruptedException if any thread interrupted the
* current thread before or while the current thread
* was waiting for a notification. The <i>interrupted
* status</i> of the current thread is cleared when
* this exception is thrown.
* @see java.lang.Object#notify()
* @see java.lang.Object#notifyAll()
*/
@FastNative
public final native void wait() throws InterruptedException;
/**
* Wakes up a single thread that is waiting on this object's
* monitor. If any threads are waiting on this object, one of them
* is chosen to be awakened. The choice is arbitrary and occurs at
* the discretion of the implementation. A thread waits on an object's
* monitor by calling one of the {@code wait} methods.
* <p>
* The awakened thread will not be able to proceed until the current
* thread relinquishes the lock on this object. The awakened thread will
* compete in the usual manner with any other threads that might be
* actively competing to synchronize on this object; for example, the
* awakened thread enjoys no reliable privilege or disadvantage in being
* the next thread to lock this object.
* <p>
* This method should only be called by a thread that is the owner
* of this object's monitor. A thread becomes the owner of the
* object's monitor in one of three ways:
* <ul>
* <li>By executing a synchronized instance method of that object.
* <li>By executing the body of a {@code synchronized} statement
* that synchronizes on the object.
* <li>For objects of type {@code Class,} by executing a
* synchronized static method of that class.
* </ul>
* <p>
* Only one thread at a time can own an object's monitor.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of this object's monitor.
* @see java.lang.Object#notifyAll()
* @see java.lang.Object#wait()
*/
@FastNative
public final native void notify();
/**
* Wakes up all threads that are waiting on this object's monitor. A
* thread waits on an object's monitor by calling one of the
* {@code wait} methods.
* <p>
* The awakened threads will not be able to proceed until the current
* thread relinquishes the lock on this object. The awakened threads
* will compete in the usual manner with any other threads that might
* be actively competing to synchronize on this object; for example,
* the awakened threads enjoy no reliable privilege or disadvantage in
* being the next thread to lock this object.
* <p>
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of this object's monitor.
* @see java.lang.Object#notify()
* @see java.lang.Object#wait()
*/
@FastNative
public final native void notifyAll();
(1).wait(),notify(),notifyAll()都是本地方法,并且為final方法呻纹,無法被重寫
(2).wait(),notify(),notifyAll()堆生,是object的方法专缠,不是Thread的方法
(3).調(diào)用某個對象的wait()的方法能讓當前線程阻塞雷酪,并且,當前線程必須擁有此對象的monitor
(4).調(diào)用某個對象的notify()方法能夠喚醒一個正在等待這個對象monitor的線程囤官,度過由多個線程在等待這個monitor循集,則只能喚醒其中一個(按等待順序)
(5).調(diào)用notifyAll()能狗煥醒所有正在等待這個對象的monitor的線程