侧边栏壁纸
博主头像
快乐江湖的博客博主等级

更多内容请点击CSDN关注“快乐江湖”

  • 累计撰写 127 篇文章
  • 累计创建 33 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

第一章Java多线程基础-第五节:wait和notify

快乐江湖
2023-06-25 / 0 评论 / 0 点赞 / 7 阅读 / 10074 字

由于线程之间的执行是抢占式的,所以线程之间的执行的先后顺序难以预知。但在实际开发中有时我们需要各个线程以特定的顺序执行,例如生产者与消费者模型中

  • 只有生产者线程生产出了产品消费者线程才能去取
  • 只有消费者线程消费了产品(有冗余空间后)生产者线程才能生产

在Java多线程中,要完成这个协调工作会涉及如下方法

  • wait()/wait(long timeout):让当前线程进入等待状态
  • notify():唤醒在当前对象上等待的线程
  • notifyAll():同上

注意:waitnotifynotifyAll都是Object类的方法,这意味着可以使用任意类的实例能都调用这些方法

一:wait()方法

wait()方法:线程执行到wait就会发生阻塞,直到另一个线程调用notify将此wait唤醒。wait要搭配synchronized使用,脱离synchronized使用wait会直接抛出异常。执行到wait会做以下三件事情

  • 释放当前的锁
  • 使线程进入等待
  • 满足一定条件,结束等待,尝试获取锁

wait结束等待的条件有

  • 其他线程调用该对象的notify方法
  • wait等待时间超时(wait(long timeout)
  • 其他线程调用该等待线程的interrupted方法,导致wait抛出InterruptedException

如下

public class TestDemo {
    public static void main(String[] args) {
        Object object = new Object();
        System.out.println("wait之前");
        synchronized (object){
            try {
                object.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println("wait之后");

    }
}

二:notify()方法

notify()方法:用于唤醒等待的线程,需要在同步方法或同步块中调用。注意

  • 如果有多个线程等待,则由线程调度器随机挑选出一个处于wait状态的线程
  • notify方法之后,当前线程不会马上释放该对象锁,在退出同步代码块之后才会释放对象锁

如下是一个典型的例子

public class TestDemo {
    public static void main(String[] args) {
        //准备一个对象,需要保证wait和notify是同一个对象
        Object object = new Object();

        //第一个线程,进行wait操作
        Thread t1 = new Thread("t1"){
            @Override
            public void run(){
                while(true){
                    synchronized (object){
                        System.out.println(Thread.currentThread().getName() + "进入并占用锁,持续3s");
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            System.out.println(Thread.currentThread().getName() + "等待并释放锁");
                            object.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        System.out.println("等待结束," + Thread.currentThread().getName() + "重新获取到锁");
                    }
                }
            }
        };
        t1.start();

        //第二个线程,进行notify
        Thread t2 = new Thread("t2"){
            @Override
            public void run(){
                while(true){
                    synchronized (object){
                        System.out.println(Thread.currentThread().getName() + "进入并占用锁,持续3s");
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        System.out.println(Thread.currentThread().getName() + "进行notify");
                        object.notify();

                        System.out.println("notify完成,让" + Thread.currentThread().getName() + "歇3s");
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }

                    }
                    System.out.println(Thread.currentThread().getName() + "已处在synchronized外,再歇10s");
                    try {
                        Thread.sleep(12000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
            }
        };

        t2.start();
    }
}

下面是一个动图,展示了程序的运行过程

0

评论区