当前位置: 首页 > news >正文

Java多线程中wait, notify and notifyAll的使用

本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example

在Java的Object类中有三个final的方法同意线程之间进行资源对象锁的通信,他们各自是: wait(), notify() and notifyAll()。

调用这些方法的当前线程必须拥有此对象监视器。否则将会报java.lang.IllegalMonitorStateException exception异常。

wait

Object的wait方法有三个重载方法,当中一个方法wait() 是无限期(一直)等待,直到其他线程调用notify或notifyAll方法唤醒当前的线程;另外两个方法wait(long timeout) 和wait(long timeout, int nanos)同意传入 当前线程在被唤醒之前须要等待的时间,timeout为毫秒数,nanos为纳秒数。

notify

notify方法仅仅唤醒一个等待(对象的)线程并使该线程開始运行。

所以假设有多个线程等待一个对象,这种方法仅仅会唤醒当中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。

notifyAll

notifyAll 会唤醒全部等待(对象的)线程,虽然哪一个线程将会第一个处理取决于操作系统的实现。

这些方法能够使用于“生产者-消费者”问题,消费者是在队列中等待对象的线程,生产者是在队列中释放对象并通知其他线程的线程。

让我们来看一个多线程作用于同一个对象的样例。我们使用wait, notify and notifyAll方法。


通过实例来理解

Message

一个java bean类。线程将会使用它并调用wait和notify方法。

Message.java

package com.journaldev.concurrency;

public class Message {
    private String msg;

    public Message(String str){
        this.msg=str;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String str) {
        this.msg=str;
    }

}

Waiter

一个Waiter类,等待其他的线程调用notify方法以唤醒线程完毕处理。

注意等待线程必须通过加synchronized同步锁拥有Message对象的监视器。

Waiter.java

package com.journaldev.concurrency;

public class Waiter implements Runnable{

    private Message msg;

    public Waiter(Message m){
        this.msg=m;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        synchronized (msg) {
            try{
                System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
                msg.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
            //process the message now
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }

}

Notifier

一个Notifier类,处理Message对象并调用notify方法唤醒等待Message对象的线程。

注意synchronized代码块被用于持有Message对象的监视器。

Notifier.java

package com.journaldev.concurrency;

public class Notifier implements Runnable {

    private Message msg;

    public Notifier(Message msg) {
        this.msg = msg;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name+" started");
        try {
            Thread.sleep(1000);
            synchronized (msg) {
                msg.setMsg(name+" Notifier work done");
                msg.notify();
                // msg.notifyAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

WaitNotifyTest

一个測试类,交付创建多个等待线程和一个通过线程,并启动这些线程。

WaitNotifyTest.java

package com.journaldev.concurrency;

public class WaitNotifyTest {

    public static void main(String[] args) {
        Message msg = new Message("process it");
        Waiter waiter = new Waiter(msg);
        new Thread(waiter,"waiter").start();

        Waiter waiter1 = new Waiter(msg);
        new Thread(waiter1, "waiter1").start();

        Notifier notifier = new Notifier(msg);
        new Thread(notifier, "notifier").start();
        System.out.println("All the threads are started");
    }

}

当我们调用以上的代码时能够看到下面的输出。但并没有结束(完毕),由于有两个线程等待同一个Message对象。但notify()方法仅仅能唤醒一个线程。还有一个线程仍然在等待被唤醒。

notify()

waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifying work done

假设我们凝视掉Notifier类中的notify() 方法的调用,并打开notifyAll() 方法的调用,将会有下面的输出信息。

notifyAll()

waiter waiting to get notified at time:1356318917118
waiter1 waiting to get notified at time:1356318917118
All the threads are started
notifier started
waiter1 waiter thread got notified at time:1356318918120
waiter1 processed: notifier Notifying work done
waiter waiter thread got notified at time:1356318918120
waiter processed: notifier Notifying work done

一旦notifyAll()方法唤醒全部的Waiter线程。程序将会运行完毕并退出。

相关文章:

  • 用Android Studio构建及运行android app
  • ArchSummit北京2015精彩回顾
  • Ubuntu OS应用Runtime Enviroment
  • [转]如何判断js中的数据类型
  • 武汉Uber优步司机奖励政策(12月21日-12.27日)
  • Java基础学习总结(5)——多态
  • 【CURL】PHP的CURL开发项目最佳实践
  • WordPress 全方位优化指南(上)
  • 光播的一些属性设置
  • iOS Swizzle
  • 我的Python 学习之旅 从0开始的小白
  • excel文件怎么使用php进行处理
  • MongoDB常用命令
  • [MFC] VS2013版本MFC工程移植到VC6.0上
  • 关于APP,原生和H5开发技术的争论
  • 【Linux系统编程】快速查找errno错误码信息
  • ➹使用webpack配置多页面应用(MPA)
  • Consul Config 使用Git做版本控制的实现
  • Docker 笔记(2):Dockerfile
  • EOS是什么
  • IP路由与转发
  • javascript从右向左截取指定位数字符的3种方法
  • java小心机(3)| 浅析finalize()
  • JS笔记四:作用域、变量(函数)提升
  • js写一个简单的选项卡
  • leetcode讲解--894. All Possible Full Binary Trees
  • php面试题 汇集2
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • swift基础之_对象 实例方法 对象方法。
  • vue 个人积累(使用工具,组件)
  • vue-router 实现分析
  • 基于HAProxy的高性能缓存服务器nuster
  • 解决iview多表头动态更改列元素发生的错误
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何编写一个可升级的智能合约
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 主流的CSS水平和垂直居中技术大全
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 浅谈sql中的in与not in,exists与not exists的区别
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • #FPGA(基础知识)
  • #每日一题合集#牛客JZ23-JZ33
  • $.proxy和$.extend
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (1)Nginx简介和安装教程
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (多级缓存)缓存同步
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (一)Dubbo快速入门、介绍、使用
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)Oracle存储过程编写经验和优化措施
  • (转)详解PHP处理密码的几种方式
  • .NET Core 通过 Ef Core 操作 Mysql