线程操作wait和notify

来源:互联网 发布:淘宝号被天猫蚁盾 编辑:程序博客网 时间:2024/05/14 17:27

线程进入运行状态之后,可以根据条件触发转为“等待阻塞

运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,


如下代码:

1、定义两个测试线程类

public class WaitTest1 extends Thread {private Object look;public WaitTest1(Object look) {this.look = look;}@Overridepublic void run() {try {synchronized (look) {System.out.println("wait start...");look.wait();System.out.println("wait end...");}} catch (Exception e) {e.printStackTrace();}}}public class WaitTest2 extends Thread {private Object look;public WaitTest2(Object look) {this.look = look;}@Overridepublic void run() {try {synchronized (look) {System.out.println("notify start...");look.notify();System.out.println("notify end...");}} catch (Exception e) {e.printStackTrace();}}}

2、测试类

public class WaitMain {public static void main(String[] args) {try {Object look = "abc";WaitTest1 thread1 = new WaitTest1(look);WaitTest2 thread2 = new WaitTest2(look);thread1.start();// 两秒后唤醒Thread.sleep(2000);thread2.start();} catch (Exception e) {e.printStackTrace();}}}


上面代码实现了线程的等待wait和唤醒notify,运行之后输出:

wait start...
wait end...
notify start...
notify end...


说明:

在执行wait()或者notify()之前必须先获得该对象的对象级别锁,即:只能在同步方法或者同步块中调用这两个方法。

关键字synchronized可以将任何一个Object对象作为同步对象来看待,而Java为每一个Object都实现了wait()和notify()方法,
他们必须用在被synchronized同步的Object临界区内。通过调用wait()方法可以使处于临界区内的线程进入等待状态,同时释放被同步对象的锁。
而notify操作可以唤醒一个因调用了wait操作而处于阻塞状态的线程,使其进入就绪状态( 注:是就绪状态,而不是运行状态),被唤醒的线程会试图重新获得临界区的控制权,也就是锁,并继续执行临界区内wait之后的代码。
如果发出notify操作时没有处于阻塞状态的线程,那么该命令会被忽略。

wait()方法可以使调用该方法的线程释放该共享资源的锁,然后从运行状态推出,进入等待队列,直到被再次唤醒。
notify()方法可以随机唤醒等待队列中等待该共享资源的“一个”线程,并使该线程退出等待队列,进入可运行状态,也就是notify()方法仅通知"一个"线程。
notifyAll()方法可以使所有正在等待队列中等待该共享资源的“全部”线程从等待状态退出,进入可运行状态。此时优先级最高的那个线程最先执行,但也有可能是随机执行,因为这要取决于JVM虚拟机的实现。

注意方法notify()被执行后,不会释放锁,必须执行完notify()方法所在的同步synchronized代码块后才会释放锁,这一点需要注意的。

顺便附上线程状态转换图:







原创粉丝点击