[笔记]Java多线程学习之wait,notify,notifyAll | 祭夜博客
  • 欢迎光临,这个博客颜色有点多

[笔记]Java多线程学习之wait,notify,notifyAll

JAVA msojocs 4年前 (2020-06-28) 2233次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

记录

this.notify();

功能:

  1. 不是唤醒正在执行this.notify();的当前线程
  2. 而是唤醒一个现在正在等待(wait) this对象 的其它线程
  3. 如果有多个线程正在等待(wait) this对象 ,通常是唤醒最先等待(wait) this对象 的线程
  4. 但具体唤醒哪一个,是由系统调度器控制的,程序员无法控制

aa.wait();

  1. 将执行aa.wait();的当前线程转入阻塞状态,让出CPU的控制权
  2. 释放对aa的锁定
  3. 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。

aa.notify();

  1. 假设执行aa.notify();的当前线程为T1,如果当前时刻有其他线程因为执行了aa.wait()而陷入阻塞状态,则唤醒其中一个
  2. 所谓唤醒是令该线程从因wait而陷入阻塞的状态转入就绪状态
  3. 若在执行aa.notify();前没有线程处于wait状态,那么程序也不会出错,相当于唤醒了0个线程

aa.notifyAll()

  1. 唤醒其它所有的因执行了aa.wait()而陷入阻塞状态的线程

在多线程中要测试某个条件的变化,使用if 还是while?

选用while
  1. 在多线程情况下,在wait过程中cnt可能会被其它线程修改,导致恢复后条件仍然成立
  2. notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。所以在进行条件判断时候,可以先把 wait 语句忽略不计来进行考虑;显然,要确保程序一定要执行,并且要保证程序直到满足一定的条件再执行,要使用while进行等待,直到满足条件才继续往下执行。

以下是简易的生产消费问题:

[笔记]Java多线程学习之wait,notify,notifyAll

 

public class produceConsume {
    public static void main(String[] args) {
        SynStack ss = new SynStack();
        Producer p = new Producer(ss);
        Consumer c = new Consumer(ss);

        Thread t1 = new Thread(p);  // 生产线程
        Thread t2 = new Thread(c);  // 消费线程
        t1.start();
        t2.start();
    }
}

class SynStack {

    private char[] data = new char[6];
    private int cnt = 0;    // 表示数组有效元素个数

    public synchronized void push(char ch)
    {
        while(cnt == data.length)   // 为什么不用if 【在多线程情况下,在wait过程中cnt可能会被其它线程修改,导致恢复后条件仍然成立】
        {
            // 暂停
            try {
                System.out.println("exc push wait");
                this.wait();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("push wait error");
            }
            System.out.println("push resume");

        }
        this.notify();
        
        data[cnt] = ch;
        cnt++;
        System.out.printf("生产线程正在生产第%d个产品:%c\n", cnt, ch);
    }

    public synchronized char pop()
    {
        char ch;
        while(cnt == 0)
        {
            // 暂停
            try {
                // System.out.println("exc pop wait");
                this.wait();
            } catch (Exception e) {
                System.out.println("pop error");
            }
            System.out.println("pop resume");
        }
        // System.out.println("awake");
        this.notify();

        ch = data[cnt - 1];
        System.out.printf("消费线程正在消费第%d个产品:%c\n", cnt, ch);
        --cnt;
        return ch;
    }
}

class Producer implements Runnable {
    private SynStack ss = null;

    public Producer(SynStack ss)
    {
        this.ss = ss;
    }
    public void run()
    {
        char ch;
        for (int i = 0; i < 20; i++) {
            // try {
            //     Thread.sleep(1000);
            // } catch (Exception e) {
            //     e.printStackTrace();
            // }
            ch = (char)('a' + i);
            ss.push(ch);
        }
    }
}

class Consumer implements Runnable {

    private SynStack ss = null;

    public Consumer(SynStack ss)
    {
        this.ss = ss;
    }
    public void run()
    {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            ss.pop();
        }
    }
}

祭夜の咖啡馆 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:[笔记]Java多线程学习之wait,notify,notifyAll
喜欢 (0)
[1690127128@qq.com]
分享 (0)
发表我的评论
取消评论
OwO表情
贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址