文档章节

Java:使用wait()与notify()实现线程间协作

We911
 We911
发布于 2017/02/08 10:12
字数 895
阅读 2
收藏 0
Java:使用wait()与notify()实现线程间协作

原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://zhangjunhd.blog.51cto.com/113473/71387
使用wait()与notify()/notifyAll()可以使得多个任务之间彼此协作。
1. wait()与notify()/notifyAll()
调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁。这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中。可以通过notify()/notifyAll(),或者时间到期,从wait()中恢复执行。
只能在同步控制方法或同步块中调用wait()、notify()和notifyAll()。如果在非同步的方法里调用这些方法,在运行时会抛出IllegalMonitorStateException异常。
2.模拟单个线程对多个线程的唤醒
模拟线程之间的协作。Game类有2个同步方法prepare()和go()。标志位start用于判断当前线程是否需要wait()。Game类的实例首先启动所有的Athele类实例,使其进入wait()状态,在一段时间后,改变标志位并notifyAll()所有处于wait状态的Athele线程。
Game.java
package concurrency;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

class Athlete  implements Runnable {
     private  final  int id;
     private Game game;

     public Athlete( int id, Game game) {
       this.id = id;
       this.game = game;
    }

     public  boolean equals(Object o) {
       if (!(o  instanceof Athlete))
         return  false;
      Athlete athlete = (Athlete) o;
       return id == athlete.id;
    }

     public String toString() {
       return  "Athlete<" + id +  ">";
    }

     public  int hashCode() {
       return  new Integer(id).hashCode();
    }

     public  void run() {
       try {
        game.prepare( this);
      }  catch (InterruptedException e) {
        System.out.println( this +  " quit the game");
      }
    }
  }

public  class Game  implements Runnable {
     private Set<Athlete> players =  new HashSet<Athlete>();
     private  boolean start =  false;

     public  void addPlayer(Athlete one) {
      players.add(one);
    }

     public  void removePlayer(Athlete one) {
      players.remove(one);
    }

     public Collection<Athlete> getPlayers() {
       return Collections.unmodifiableSet(players);
    }

     public  void prepare(Athlete athlete)  throws InterruptedException {
      System.out.println(athlete +  " ready!");
       synchronized ( this) {
         while (!start)
        wait();
         if (start)
          System.out.println(athlete +  " go!");
      }
    }

     public  synchronized  void go() {
      notifyAll();
    }
    
     public  void ready() {
      Iterator<Athlete> iter = getPlayers().iterator();
       while (iter.hasNext())
         new Thread(iter.next()).start();
    }

     public  void run() {
      start =  false;
      System.out.println( "Ready......");
      System.out.println( "Ready......");
      System.out.println( "Ready......");
      ready();
      start =  true;
      System.out.println( "Go!");
      go();
    }

     public  static  void main(String[] args) {
      Game game =  new Game();
       for ( int i = 0; i < 10; i++)
        game.addPlayer( new Athlete(i, game));
       new Thread(game).start();
    }
}
结果:
Ready......
Ready......
Ready......
Athlete<0> ready!
Athlete<1> ready!
Athlete<2> ready!
Athlete<3> ready!
Athlete<4> ready!
Athlete<5> ready!
Athlete<6> ready!
Athlete<7> ready!
Athlete<8> ready!
Athlete<9> ready!
Go!
Athlete<9> go!
Athlete<8> go!
Athlete<7> go!
Athlete<6> go!
Athlete<5> go!
Athlete<4> go!
Athlete<3> go!
Athlete<2> go!
Athlete<1> go!
Athlete<0> go!
3.模拟忙等待过程
MyObject类的实例是被观察者,当观察事件发生时,它会通知一个Monitor类的实例(通知的方式是改变一个标志位)。而此Monitor类的实例是通过忙等待来不断的检查标志位是否变化。
BusyWaiting.java
import java.util.concurrent.TimeUnit;

class MyObject  implements Runnable {
     private Monitor monitor;

     public MyObject(Monitor monitor) {
       this.monitor = monitor;
    }

     public  void run() {
       try {
        TimeUnit.SECONDS.sleep(3);
        System.out.println( "i'm going.");
        monitor.gotMessage();
      }  catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
}

class Monitor  implements Runnable {
     private  volatile  boolean go =  false;

     public  void gotMessage()  throws InterruptedException {
      go =  true;
    }

     public  void watching() {
       while (go ==  false)
        ;
      System.out.println( "He has gone.");
    }

     public  void run() {
      watching();
    }
}

public  class BusyWaiting {
     public  static  void main(String[] args) {
      Monitor monitor =  new Monitor();
      MyObject o =  new MyObject(monitor);
       new Thread(o).start();
       new Thread(monitor).start();
    }
}
结果:
i'm going.
He has gone.
4.使用wait()与notify()改写上面的例子
下面的例子通过wait()来取代忙等待机制,当收到通知消息时,notify当前Monitor类线程。
Wait.java
package concurrency.wait;

import java.util.concurrent.TimeUnit;

class MyObject  implements Runnable {
     private Monitor monitor;

     public MyObject(Monitor monitor) {
       this.monitor = monitor;
    }

     public  void run() {
       try {
        TimeUnit.SECONDS.sleep(3);
        System.out.println( "i'm going.");
        monitor.gotMessage();
      }  catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
}

class Monitor  implements Runnable {
     private  volatile  boolean go =  false;

     public  synchronized  void gotMessage()  throws InterruptedException {
      go =  true;
      notify();
    }

     public  synchronized  void watching()  throws InterruptedException {
       while (go ==  false)
        wait();
      System.out.println( "He has gone.");
    }

     public  void run() {
       try {
        watching();
      }  catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
}

public  class Wait {
     public  static  void main(String[] args) {
      Monitor monitor =  new Monitor();
      MyObject o =  new MyObject(monitor);
       new Thread(o).start();
       new Thread(monitor).start();
    }
}

本文转载自:http://blog.csdn.net/liduanw/article/details/8203474

共有 人打赏支持
We911
粉丝 1
博文 63
码字总数 0
作品 0
深圳
程序员
私信 提问
Java编程的逻辑 -- 并发章 -- 线程的基本协作机制

线程的基本协作 线程的基本协作示例 总结 线程的基本协作 多线程间除了竞争访问同一资源外,也经常需要相互协作的去执行一些任务。而对于协作的基本机制用的最多的无疑是wait/notify。 协作的...

HikariCP
2018/06/22
0
0
【synchronized底层原理之1】Monitor Object 设计模式

Monitor Object设计模式源于C++:被JDK开发人员借鉴到了Java中并且对Monitor Object设计模式进行了封装。所以Java程序员在开发层面上对Monitor Object设计模式是无感知的(指对Monitor Objec...

karma123
2018/09/10
0
0
Java多线程学习(四)等待/通知(wait/notify)机制

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
2018/04/16
0
0
java并发编程(2)——wait和notify解析

JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内...

十二缸帕萨特
2014/04/12
0
0
多线程编程学习三(线程间通信).

一、概要 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一。可以说,使线程进行通信后,系统之间的交互性会更强大...

jmcui
2017/09/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

postgres预写式日志的内核实现详解-heap2类型

导读: postgres预写式日志的内核实现详解-概述 postgres预写式日志的内核实现详解-wal记录结构 postgres预写式日志的内核实现详解-wal记录写入 postgres预写式日志的内核实现详解-wal记录读...

movead
15分钟前
0
0
ToolBar控件在C#开发APP中的使用方式【附案例源码】——Smobiler移动开发平台

控件说明 底部工具栏控件。 效果演示 其他效果 该界面为仿淘宝UI制作的一个简单的UI模板,源码获取方式请拉至文章末尾。 特色属性 属性 属性说明 Direction(相对布局) 容器主轴方向。 Flex...

amanda112
26分钟前
1
0
模块

AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等...

gtandsn
33分钟前
1
0
代码之外的生存指南,这6本书助你提升软实力

上期盟主向大家推荐了6本技术类书籍,引起了热烈反响。那么,工作之余,还有哪些好书能够为你打开更多的精彩世界呢?本期,多位知名企业的技术大咖将继续为您带来好书推荐,在新的一年里,为...

安卓绿色联盟
36分钟前
3
0
5分钟用Jitpack发布开源库

作者: 菜刀文 Demo:https://github.com/helen-x/JitPackReleaseDemo 项目开发中会用到很多开源库, 他们一般通过Maven/Gradle依赖进来的. 演而优则唱,开发越来越溜以后, 你是否也蠢蠢欲动,想发...

SuShine
42分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部