Java多线程系列4 线程交互(wait和notify方法)

wait()/ notify()/ notifyAll()

任何Object对象都可以作为这三个方法的主调,但是不推荐线程对象调用这些方法。

1使用wait()、notify()和notifyAll()时需要首先对调用对象加锁【必须使用在同步代码块】
2调用wait()方法后,线程状态会从RUNNING变为WAITING,并将当线程加入到lock对象的等待队列中【会释放锁】 ,后面的代码就不执行了 。当被唤醒并被执行时,是接着上次执行到的wait()方法代码后面继续往下执行的。
3调用notify()或者notifyAll()方法后,等待在lock对象的等待队列的线程不会马上从wait()方法返回,必须要等到调用notify()或者notifyAll()方法的线程将lock锁释放,等待线程才有机会从等待队列返回。这里只是有机会,因为锁释放后,等待线程会出现竞争,只有竞争到该锁的线程才会从wait()方法返回,其他的线程只能继续等待

下面代码演示 

public class WaitNotifyThread {
    //条件是否满足的标志
    private static boolean flag = true;
    //对象的监视器锁
    private static Object lock = new Object();

    public static void main(String[] args){
        Thread waitThread = new Thread(new WaitThread(),"WaitThread");
        waitThread.start();
   
        Thread notifyThread = new Thread(new NotifyThread(),"NotifyThread");
        notifyThread.start();
    }

    /**
     * 等待线程
     */
    private static class WaitThread implements Runnable{
        public void run() {
            //加锁,持有对象的监视器锁
            synchronized (lock){
                //只有成功获取对象的监视器才能进入这里
                //当条件不满足的时候,继续wait,直到某个线程执行了通知
                //并且释放了lock的监视器(简单来说就是锁)才能从wait
                //方法返回
                while (flag){
                    try {
                        System.out.println(Thread.currentThread().getName() + " flag is true"
                               );
                        lock.wait(); //相当于睡眠 但是释放锁的
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //条件满足,继续工作
                System.out.println(Thread.currentThread().getName() + " flag is false "
                       );
            }
        }
    }

    /**
     * 通知线程
     */
    private static class NotifyThread implements Runnable{
        public void run() {
            synchronized (lock){
                //获取lock锁,然后执行通知,通知的时候不会释放lock锁
                //只有当前线程退出了lock后,waitThread才有可能从wait返回
                System.out.println(Thread.currentThread().getName() + " holds lock "
                       );
                lock.notifyAll(); //唤醒wait 但是只有释放代码块以后  wait变成就绪  
                flag = false;
                try {
        			Thread.sleep(1000);
        		} catch (InterruptedException e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		}
            }
            //再次加锁
            synchronized (lock){
                System.out.println(Thread.currentThread().getName() + " holds lock again "
                       );
                try {
        			Thread.sleep(1000);
        		} catch (InterruptedException e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		}
            }
        }
    }
}

  运行结果会有两种

  

  或者

  

 这个例子只是想说明 调用notify 或者notifyAll 并不会释放锁 要等到同步代码执行完成以后 才会释放  释放以后,两个线程的执行是不确定的 

 所以会有2个结果

  

 

       

posted on 2017-05-10 17:48  一只小蜗牛12138  阅读(159)  评论(0编辑  收藏  举报

导航