[基础]Object.wait()方法

先来看一下Object类的wait()方法定义:实际上调用了一个带有参数的wait本地方法;

public final void wait() throws InterruptedException {
    wait(0);
}

本地方法wait(long timeout),参数传递为0,表示当前线程一直等待直到被通知(notify/notifyAll); 

public final native void wait(long timeout) throws InterruptedException;

看一下wait()方法的javadoc,如下片段; 

     * <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>

简译为:当前线程必须持有对象的锁。当前线程释放了持有的对象锁,一直等待到其他线程发出通知--通知等待这个对象锁的线程醒来。通知的方式是通过调用notify或notifyAll方法。当前线程然后等待重新获取对象锁,接着继续执行。

问题:如果直接调用wait方法会如何? 如: new Object().wait();

        try {
            new Object().wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

很遗憾,会报错; 

Exception in thread "main" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)

就是说当前线程如果没有获取对象锁,是无法直接调用wait()方法的。wait()方法的javadoc上已经写明:

     * @throws  IllegalMonitorStateException  if the current thread is not
     *               the owner of the object's monitor.

那么wait()方法的本质是什么呢?

本质是当前线程释放持有的对象锁,当前线程进入等待队列,当然也让出了OS分配的CPU时间片,详细见这里

本地方法wait(long timeout)有一段重要的javadoc,如下;调用wait方法会使当前线程进入一个等待集合里,"for this object"意思是【 如:obj.wait() 】 这些等待集合里的线程都是为了获取obj对象锁。"unlocks only this object"意思是仅仅释放obj的对象锁。

当前线程等待obj的对象锁,但是持有的其他对象锁是一直持有的。

     * <p>
     * Note that the {@code wait} method, as it places the current thread
     * into the wait set for this object, unlocks only this object; any
     * other objects on which the current thread may be synchronized remain
     * locked while the thread waits.
     * <p>

 

做个练习题吧,两个线程,一个打印奇数,一个打印偶数;保证打印出来的数字是连续的,如0,1,2,3,4....

public class TestWait {

    private Object lock = new Object();
    private int i = 0; //初始化为0:保证打印偶数线程先输出

    private class PrinterRunnable implements Runnable {
        private int remainder;

        public PrinterRunnable(int remainder) {
            this.remainder = remainder;
        }

        @Override
        public void run() {
            synchronized (lock) {
                while (i < 100) {
                    if (i % 2 == remainder) {
                        System.out.println(Thread.currentThread().getName() + "__" + i);
                        i++;
                    }

                    lock.notifyAll();

                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void runThreads() {
        Thread printEvenThread = new Thread(new PrinterRunnable(0));
        Thread printOddThread = new Thread(new PrinterRunnable(1));

        printOddThread.start(); //让打印奇数线程先启动(实际上哪个线程先执行是未知的)
        printEvenThread.start();
    }

    public static void main(String[] args) {
        new TestWait().runThreads();
    }

}

注意:notify/notifyAll() 要在wait方法之前执行,否则线程一直等待,得不到通知。

程序输出:

Thread-0__0
Thread-1__1
Thread-0__2
Thread-1__3
Thread-0__4
Thread-1__5
Thread-0__6
Thread-1__7
Thread-0__8
.
.
.

The End.

 

转载于:https://my.oschina.net/placeholder/blog/1546620

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值