wait()和notify()

本文深入探讨Java中线程通信的实现方式,重点讲解wait()和notify()的正确使用方法,以及它们与sleep()的区别。通过实例代码展示了如何在同步块中使用这些方法,确保线程间的有效通信,避免死锁和数据不一致问题。

wait()和notify()

从https://www.cnblogs.com/toov5/p/9837373.html 可以看到他的打印是一片一片的,这边博客介绍怎么避免掉

使用notify 和 wait的时候 要注意 是在synchronize进行的,持有同一把锁

1.因为涉及到对象锁,他们必须都放在synchronized中来使用. Wait、Notify一定要在synchronized里面进行使用。

2.Wait必须暂定当前正在执行的线程,并释放资源锁,让其他线程可以有机会运行

3. notify/notifyall: 唤醒因锁池中的线程,使之运行

注意:一定要在线程同步中使用,并且是同一个锁的资源

 

一片的原因是: cpu在调度时候 读一直被调度上了

package com.toov5.thread;

//共享对象
class Res{
    public boolean flag = true;
    public String sex;
    public String name;
    
}

class inputThread extends Thread{
     public Res res;
     public inputThread(Res res) {
        this.res=res;
    }
    @Override
    public  void run() {
      int count=0; 
      while (true) {
          synchronized (res) {
               if (res.flag) {
              try {
                res.wait();   //此处一定要用res的wait!!!! 执行到这里就会阻塞了 下面的代码不会执行了  释放当前锁对象
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            }
                if (count==0) {
                    res.name="lucy";
                    res.sex="girl";    
                }else {
                    res.name="Jack";
                    res.sex="boy";
                }
                count =(count+1)%2;
                res.flag=true;  //写完了 标记当前线程为等待 然后走wait()了
                res.notify();  //通知读的线程
        }
    }
    }
}

class readThread extends Thread{
    public Res res;
    public readThread(Res res) {
        this.res=res;
    }
    
    @Override
    public void run() {
        while (true) {    
        synchronized (res) {
               if(!res.flag){
                 try {
                    res.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }    
               }
               System.out.println(res.name+","+res.sex);
               //读完了时候要 
               res.flag=false;
               res.notify();//通知写的线程
               
            }
        }        
    }
}

public class ConmunicatThreadTest {
    //开启两个线程  下面的线程 主线程 还有这俩用户线程 cpu随机的

    public static void main(String[] args) {
        Res res = new Res();
    inputThread inputThread = new inputThread(res);
    readThread  readThread = new readThread(res);
    inputThread.start();
    readThread.start();
    
    }  
       
    
}

看下结果:

 

 

分析下: 

两个线程 并行在执行 假设 flag为false  读的线程会等待  cpu执行权让给写的线程同时锁也会释放掉  

                                         写的时候 读的线程发现为true (while(true)的情况) 等待notify() 被唤醒,被唤醒后 从wait处继续往下执行  唤醒被等待的线程~~~

 notifyall 是唤醒所有的  小伙伴们可以自己试试哈

 注意  notify 和 wait 一定要在synchronize里面使用!!!!!并且同一个锁对象的!  

 

wait与join 区别:

 wait需要唤醒  wait需要用在同步里面

 

wait与sleep区别

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

在调用sleep()方法的过程中,线程不会释放对象锁。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备

获取对象锁进入运行状态。

  sleep不去释放锁 wait释放

 

wait notify 为啥设计在object类 因为任意对象作为锁嘛 Object是任何类的祖宗~ 所以小伙伴们都明了了吧~~

 

在Java多线程编程中,`wait()` `notify()` 是用于线程间通信的重要方法,它们定义在 `Object` 类中,并且必须在同步上下文中(如 `synchronized` 方法或代码块)中使用。这两个方法的主要作用是协调多个线程的执行顺序,确保线程之间可以安全地共享资源。 ### wait() 方法 `wait()` 方法的作用是使当前线程进入等待状态,直到其他线程调用该对象上的 `notify()` 或 `notifyAll()` 方法来唤醒它。调用 `wait()` 时,当前线程会释放持有的对象锁,并进入该对象的等待队列中[^4]。 一个典型的使用模式如下: ```java synchronized (lock) { while (!condition) { lock.wait(); } // 执行后续操作 } ``` 在此模式中,线程会在条件不满足时通过 `wait()` 进入等待状态,并在条件发生变化时被唤醒继续执行。 ### notify() 方法 `notify()` 方法用于唤醒在指定对象上等待的一个线程。如果有多个线程在等待,则由线程调度器随机选择其中一个进行唤醒。需要注意的是,调用 `notify()` 后,当前线程不会立即释放对象锁,而是要等到其所在的同步代码块或方法执行完毕后才会释放锁[^1]。 以下是一个简单的示例说明 `notify()` 的使用: ```java public class NotifyExample { public static void main(String[] args) { Object lock = new Object(); Thread t1 = new Thread(() -> { synchronized (lock) { System.out.println("t1 开始等待"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 被唤醒"); } }); Thread t2 = new Thread(() -> { synchronized (lock) { System.out.println("t2 准备通知"); lock.notify(); System.out.println("t2 已通知"); } }); t1.start(); try { Thread.sleep(1000); // 确保 t1 先进入等待状态 } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } ``` 在这个例子中,线程 `t1` 在进入同步代码块后调用 `wait()` 方法并释放锁,而线程 `t2` 在随后调用 `notify()` 来唤醒 `t1`。 ### 使用注意事项 - **必须在同步环境中使用**:`wait()` `notify()` 必须在 `synchronized` 方法或代码块中调用,否则会抛出 `IllegalMonitorStateException` 异常[^2]。 - **避免虚假唤醒**:通常建议将 `wait()` 放在一个循环中检查条件是否满足,以防止线程在没有收到通知的情况下被唤醒。 - **notify() notifyAll() 的区别**:`notify()` 只唤醒一个等待线程,而 `notifyAll()` 唤醒所有等待线程,适用于需要处理多个线程竞争的情况[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值