线程等待和唤醒
本文参考了此博客部分内容:http://www.cnblogs.com/skywang12345/p/3479224.html
概述
在Object类中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
wait()
参考注释
节选了部分核心注释,理解它很有帮助
/**
* 调用wait的当前线程必须拥有该对象的锁
* The current thread must own this object's monitor.
*
* 这个方法会使当前线程将自己放入对象的等待集合,然后放弃它持有的锁,线程将暂时不会被调度并处于休眠状态,
* 直到以下四种情况之一的发生:
* This method causes the current thread (call it <var>T</var>) to
* place itself in the wait set for this object and then to relinquish
* any and all synchronization claims on this object. Thread <var>T</var>
* becomes disabled for thread scheduling purposes and lies dormant
* until one of four things happens:
*
* ①其他线程调用同一个对象的notify方法,而此线程正好是被随机选中要唤醒的线程
* Some other thread invokes the {@code notify} method for this
* object and thread <var>T</var> happens to be arbitrarily chosen as
* the thread to be awakened.
*
* ②其他线程调用了同一个对象的notifyAll方法
* Some other thread invokes the {@code notifyAll} method for this
* object.
*
* ③其他线程中断了该线程
* Some other thread {@linkplain Thread#interrupt() interrupts}
* thread <var>T</var>.
*
* ④wait(long waitTime)参数中的等待时间过去了,如果等待时间为0则会一直等待唤醒
* The specified amount of real time has elapsed, more or less. If
* {@code timeout} is zero, however, then real time is not taken into
* consideration and the thread simply waits until notified.
*
* 线程在被唤醒后,将会从该对象的等待集中删除,并重新启动线程调度,
* 在与其他线程竞争到锁后,wait方法才返回。对象和线程的状态将会与调用wait时完全相同
* The thread <var>T</var> is then removed from the wait set for this
* object and re-enabled for thread scheduling. It then competes in the
* usual manner with other threads for the right to synchronize on the
* object; once it has gained control of the object, all its
* synchronization claims on the object are restored to the status quo
* ante - that is, to the situation as of the time that the {@code wait}
* method was invoked. Thread <var>T</var> then returns from the
* invocation of the {@code wait} method. Thus, on return from the
* {@code wait} method, the synchronization state of the object and of
* thread {@code T} is exactly as it was when the {@code wait} method
* was invoked.
*
* 此方法只能由该对象监视器的所有者线程调用,查看notify方法,了解如何成为监视器所有者。
* 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.
notify()、notifyAll()
参考注释
notify()
/**
* 如果有任何线程在等待此对象监视器(锁),则随机选择其中一个线程唤醒。
* 线程调用wait方法来等待对象的监视器(锁)
* 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.
*
* 被唤醒的对象并不会立马开始执行,必须等到当前线程释放该对象上的锁,然后被
* 唤醒的线程将会公平的与其他线程进行竞争该锁。
* 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.
*
* notify方法必须是持有该对象的监视器的线程才能够调用,以下有三种方法可以成为监视器的拥有者
* <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.
*
notifyAll()与notify()大致相同,这里只列出不同的
/**
* 唤醒此对象监视器上的所有线程,对象通过wait方法来等待对象的监视器
* 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.
*/
实例
wait()和notify()
这里使用一个经典的例子加深对wait的理解
// WaitTest.java的源码
class ThreadA extends Thread{
public ThreadA(String name) {
super(name);
}
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName()+" call notify()");
// 唤醒当前的wait线程
notify();
}
}
}
public class WaitTest {
public static void main(String[] args) {
ThreadA t1 = new ThreadA("t1");
synchronized(t1) {
try {
// 启动“线程t1”
System.out.println(Thread.currentThread().getName()+" start t1");
t1.start();
// 主线程等待t1通过notify()唤醒。
System.out.println(Thread