Java 多线程编程之:notify 和 wait 用法

wait和notify简介

wait和notify都输属于object的方法

object.wait():  暂停一个线程.

object.notify():  唤醒一个线程.

想要实现wait和notify方法首先需要一个object对象. 在多个线程之间,我们可以通过调用同一个对象的wait()和notify()来实现不同线程之间的可见.

 

对象控制权(monitor)

在使用wait和notify之前, 我们需要了解对象的控制权(monitor). 在java中任何一个时刻, 对象的控制权只能被一个线程拥有.

代码说明:

复制代码
public class ThreadTest2 {
public static void main(String[] args) {
Object object = new Object();

new Thread(new Runnable() {
@Override
public void run() {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}).start();
}
}
复制代码

会报错,因为我们没有获取对象的控制权.

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.ultiwill.test.threads.ThreadTest2$1.run(ThreadTest2.java:15)
    at java.lang.Thread.run(Thread.java:748)

出错的代码在object.wait(), 这里我们需要了解一下事实:

1.无论执行对象的wait(), notify(), notifyAll()方法, 必须保证当前运行的线程获取该对象的控制权.

2.我们可以通过同步锁来获得对象的控制权, 例如: synchronized代码块.

代码改造:

复制代码
public class ThreadTest2 {
    public static void main(String[] args) {
        Object object = new Object();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object){
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        
    }
}
复制代码

这样就不会报错.

 

扩展题:

使用两个线程, 一个输出1,3,5,7...99 另一个输出2,4,6,8...100, 最后stdout中按顺序输出1,2,3,4...100
复制代码
public class ThreadDemo {

    private static Object object = new Object();

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object) {
                    for (int i = 0; i <= 100; i += 2) {
                        //唤醒线程
                        object.notify();

                        System.out.println(i);
                        try {
                            //暂停线程
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object) {
                    for (int i = 1; i <= 100; i += 2) {
                        //唤醒线程
                        object.notify();

                        System.out.println(i);
                        try {
                            //暂停线程
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }).start();

    }


}
复制代码

 

posted @   所向披靡zz  阅读(578)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示