多线程中的wait和notify

这篇具有很好参考价值的文章主要介绍了多线程中的wait和notify。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、wait和notify

由于线程之间是抢占式执行的,所以线程之间的执行先后顺序难以预知。但实际上是希望合理的协调多个线程之间的执行先后顺序。

多线程中的wait和notify

 完成这个协调工作,主要涉及到三个方法

*wait()/wait(long timeout);让当前线程进入等待状态。

*notify()/notifyAll();唤醒在当前对象上等待的线程。

注意:wait,notify,notifyAll都是Object的方法,而之前提到的join()(等待当前线程运行结束)方法是Thread类中的方法,

2、wait方法

wait做的事情:

*使当前执行的代码的线程进行等待。(把线程放到等待队列中) 

*释放当前锁

*满足一定条件就会被唤醒,重新尝试获取这个锁。

wait要搭配synchronized一起使用,脱离synchronized使用wait就会抛出异常。

wait结束等待的条件:

*其他线程调用该对象的notify()方法

*wait等待时间超时(wait提供一个带有timeout参数的版本,来指定等待时间)

*其他线程调用该等待线程的interrupted方法,导致wait抛出InterrputedException异常。

3、 notify方法

notify是唤醒等待线程的方法

*方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其他线程,对其发出通知notify(),并使它们重新获取该对象的对象锁。

*如果有多个线程等待,则有线程调度器随机挑选一个状态为wait的线程,(并没有“先来后到的原则”)。

*在notify()方法后,当前线程不会马上释放该对象锁,要等待到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

4、代码示例:

/**
 * wait()和notify()方法
 */
public class Exe_02 {
    public static void main(String[] args) {
        //定义一个锁对象
        Object locker=new Object();
        //创建调用wait()方法的线程
        Thread t1=new Thread(() ->{
            while(true){
                System.out.println("wait之前");
                try {
                    synchronized (locker) {
                        locker.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("wait之后");
                System.out.println("==============");
            }
        },"t1");
        //创建调用notify方法线程
        Thread t2=new Thread(() ->{
            while(true){
                System.out.println("notify之前");
                //加入锁
                synchronized (locker) {
                    locker.notify();
                }
                System.out.println("notify之后");
                //休眠一会
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t2");
        //启动线程
        t1.start();
        t2.start();
    }
}

多线程中的wait和notify

 执行逻辑分析:

多线程中的wait和notify

 注意:

1、当一个线程调用了wait()之后,就释放掉当前持有的锁,等待被其他线程唤醒。

2、当另一个线程调用了notify()之后, 之前调用wait()的线程被唤醒后,需要重新竞争锁资源然后再从之前wait的位置向下执行自己的逻辑。

4.1、notify()和notifyAll()

notify方法只是随机唤醒某一个线程,这个线程来获取锁;

notifyAll可以一次性唤醒所有等待的线程,这些线程全部去竞争锁,谁先拿到谁先处理。 

 5、观察多线程环境下锁状态

代码示例:

import org.openjdk.jol.info.ClassLayout;

public class Exe_03 {
    //定义一些变量
    private int count;
    private long count1=200;
    private String hello="";
    //定义一个对象变量
    private textExe_03 text03=new textExe_03();

    public static void main(String[] args) throws InterruptedException {
        //创建一个对象的实例
        Object obj=new Object();
        //打印实例布局
        System.out.println("=====任意object对象布局,起初无锁状态");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        System.out.println("延迟三秒开启偏向锁");
        //延迟3秒开启偏向锁
        Thread.sleep(3000);
        //创建本类的实例
        Exe_03 exe_03=new Exe_03();
        //打印实例布局,查看锁状态
        System.out.println("=====打印实例布局,查看锁状态");
        System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
        //调用hashCode后,保存hashCode的值
        exe_03.hashCode();
        //观察现象
        System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
        System.out.println("==============================");
        System.out.println("synchronized加锁");
        //加锁后观察锁信息
        synchronized(exe_03){
            System.out.println("第一层synchronized加锁后");
            System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
            //锁重入,观察锁信息
            synchronized(exe_03){
                System.out.println("第二层synchronized加锁后");
                System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
            }
            //释放里层的锁
            System.out.println("释放内层锁后");
            System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
        }
        //释放所有锁之后
        System.out.println("=========释放所有锁========");
        System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
        System.out.println("==============================");
        //强制执行垃圾回收
        System.gc();
        //观察GC计数
        System.out.println("+++++++调用GC后查看age的值");
        System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
        //打印类布局,调用不同的方法查看
        System.out.println("+++++查看类布局");
        System.out.println(ClassLayout.parseClass(Exe_03.class).toPrintable());
        //打印类对象布局
        System.out.println("+++++查看类对象布局");
        System.out.println(ClassLayout.parseInstance(Exe_03.class).toPrintable());
        synchronized (Exe_03.class){
            //加锁后的类对象
            System.out.println("+++++对类对象加锁后,不同的对象获取锁,观察锁升级为thin lock");
            System.out.println(ClassLayout.parseInstance(Exe_03.class).toPrintable());
        }
        //释放锁之后的类对象
        System.out.println("+++++释放锁后");
        System.out.println(ClassLayout.parseInstance(Exe_03.class).toPrintable());
        System.out.println("+++++多个锁线程参与锁竞争,观察锁状态+++++");
        Thread t1=new Thread(() ->{
            synchronized(exe_03){
                System.out.println("++++++在线程A中参与锁竞争,观察锁状态++++++");
                System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
            }
        });
        t1.start();
        Thread t2=new Thread(() ->{
            synchronized(exe_03){
                System.out.println("++++++在线程B中参与锁竞争,观察锁状态++++++");
                System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
            }
        });
        t2.start();
        Thread t3=new Thread(() ->{
            synchronized(exe_03){
                System.out.println("++++++在线程C中参与锁竞争,观察锁状态++++++");
                System.out.println(ClassLayout.parseInstance(exe_03).toPrintable());
            }
        });
        t3.start();
    }
}
class textExe_03{

}

 查看运行结果:

多线程中的wait和notify

 文章来源地址https://www.toymoban.com/news/detail-498495.html

到了这里,关于多线程中的wait和notify的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java高并发系列: 使用wait - notify实现高效异步方法

    在项目开发中, 通常会有异步执行操作, 例如: 提交一个异步清空一系列数据库中ID = ${_id} 的记录, 这个时候通常的做法是主线程将任务添加到一个异步队列中, 后台维护一个线程不断地 循环 扫描这个队列, 如果有需要执行的任务, 则执行相应的逻辑. 如下图所示: 代码实现如下

    2024年02月09日
    浏览(54)
  • 在两道多线程基础题“顺序打印”中对比一下Java中的wait()和join()

    目录 一、基础 二、进阶 有三个线程,线程名称分别为:a,b,c,每个线程打印自己的名称。 需要让他们同时启动,并按 c,b,a的顺序打印。 这道题要求打印 cba,且只打印一次。如何保证线程 cba 的执行顺序?容易想到,只需要让这三个线程按一定顺序串行执行即可,采用

    2024年02月04日
    浏览(38)
  • 面试知识点:notify是随机唤醒线程吗(唤醒线程顺序)?

    做 Java 开发的小伙伴,对 wait 方法和 notify 方法应该都比较熟悉,这两个方法在线程通讯中使用的频率非常高,但对于 notify 方法的唤醒顺序,有很多小伙伴的理解都是错误的,有很多人会认为 notify 是随机唤醒的,但它真的是随机唤醒的吗? 带着这个疑问,我们尝试休眠 1

    2024年01月24日
    浏览(49)
  • 线程异常WAITING(parking)

    现象: 在项目中线程数量持续增长,且基本无法回收关闭,线程数量一直累积达到几万,影响CPU开销和性能,导致服务器卡死,连接上服务器后输入指令提示“无可分配内存”。 查找原因: 通过ps -eLf|grep \\\'容器名\\\'|wc -l命令找到项目的所占的线程数异常庞大,通过top -p pid H也

    2024年02月16日
    浏览(37)
  • (17)线程的实例认识:wait,waitany,waitall,及经典死锁问题

         1、界面: 一个textbox,四个button。                       2、程序:前面(15)的book类与data类             1、t.Wait();         Task.Wait方法用于阻塞当前线程,并等待异步操作的完成。它是一个实例方法,针对具体的单一任务使用,用法:             task.Wait(

    2024年02月09日
    浏览(54)
  • java八股文面试[多线程]——sleep wait join yield

          sleep和wait有什么区别 sleep 方法和 wait 方法都是用来将线程进入 阻塞状态 的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应并中断,且都可以抛出 InterruptedException 异常,那 sleep 和 wait 有什么区别呢?

    2024年02月11日
    浏览(44)
  • 06 为什么需要多线程;多线程的优缺点;程序 进程 线程之间的关系;进程和线程之间的区别

    CPU、内存、IO之间的性能差异巨大 多核心CPU的发展 线程的本质是增加一个可以执行代码工人 多线程的优点 多个执行流,并行执行。(多个工人,干不一样的活) 多线程的缺点 上下文切换慢,切换上下文典型值1us vs 0.3ns/cycle CPU在执行A任务(A没有执行完)时,切换到任务B,需

    2024年02月14日
    浏览(50)
  • 进程和线程的区别 && 线程之间共享的资源

    线程和进程都是操作系统中的执行单位,但它们在以下几个方面存在区别: 1.执行环境:线程和进程都有自己的执行上下文,包括程序计数器、寄存器和栈,可以独立执行指令。 2.并发性:线程和进程都可以实现并发执行,提高系统资源利用率。 3.调度:线程和进程都需要操

    2024年02月07日
    浏览(43)
  • 多线程Synchronized锁的使用与线程之间的通讯

    多线程同时对同一个全局变量做写操作,可能会受到其他线程的干扰,就会发生线程安全问题。 Java中的全局变量是存放在堆内存中的,而堆内容对于所有线程来说是共享的。 比如下面一个简单的代码案例: 代码比较简单,我们看下面控制台的打印: 可以看到两个线程之间

    2024年02月04日
    浏览(41)
  • Java线程之间通信方式

    在实际开发时,一个进程中往往有很多个线程,大多数线程之间往往不是绝对独立的,比如说我们需要将A和B 两个线程的执行结果收集在一起然后显示在界面上,又或者比较典型的消费者-生产者模式,在这些场景下,线程间通信成了我们必须使用的手段,那么线程之间怎么通

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包