一.概述
本篇文章会对线程等待/唤醒方法进行介绍。涉及到的内容包括:
1. wait(), notify(), notifyAll(),join(),sleep(),yield()等方法介绍
2. wait()和notify()
3. wait(long timeout)和notify()
4. wait() 和 notifyAll()
5.wait()和join()
6. 为什么notify(), wait()等函数定义在Object中,而不是Thread中?
7.wait()和sleep(),yield()的区别
二.详细分析
1. wait(), notify(), notifyAll(),join(),sleep(),yield()等方法介绍
在Object.java中,定义了wait(), notify()和notifyAll()等方法。
wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
notify()唤醒在此对象锁上等待的单个线程。
notifyAll()唤醒在此对象锁上等待的所有线程。
wait()让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。
wait(long timeout) 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
wait(long timeout, int nanos) 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。
在Thread.java中,定义了join(),sleep(),yield()等方法。
join方法把指定的线程添加到当前线程中,可以不给参数直接thread.join(),也可以给一个时间参数,单位为毫秒thread.join(100)。事实上join方法是通过wait方法来实现的。比如线程A中加入了线程B.join方法,则线程A默认执行wait()方法,释放资源进入等待状态,此时线程B获得资源,执行结束后释放资源,线程A重新获取自CPU,继续执行,由此实现线程的顺序执行。
sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是它的监控状态依然保持者,当指定的时间到了又会自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。在调用sleep()方法的过程中,线程不会释放对象锁。
yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。
让我们列举一下关于以上定义重要的几点:
- Yield是一个静态的原生(native)方法
- Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程
- Yield不能保证使得当前正在运行的线程迅速转换到可运行的状态
- 它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态
2. wait()和notify()示例
/**
* @author zhaoj
* @version MyThread.java, v 0.1 2019-04-18 10:45
*/
public class MyThread extends Thread {
private Object object;
public MyThread(String name, Object object) {
super(name);
this.object = object;
}
public void run() {
synchronized (object) {
try {
System.out.println(Thread.currentThread().getName() + " wait");
object.wait();
System.out.println(Thread.currentThread().getName() + " continue");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* @author zhaoj
* @version ThreadTest.java, v 0.1 2019-04-18 10:44
*/
public class ThreadTest {
private static Object object = new Object();
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread("t1", object)