Java多线程通讯之wait,notify的区别详解

下面通过代码给大家介绍java多线程通讯之wait notify的区别,具体内容如下所示:

class Res{
 public String username;
 public String sex;
}
class Out extends Thread{
 Res res;
 public Out(Res res){
  this.res=res;
 }
 @Override
 public void run() {
  //写操作
  int count=0;
  while (true){
//   synchronized (res.getClass()){
    if(count==0){//偶数
     res.username="小明";
     res.sex="男";
    } else {//奇数
     res.username="小红";
     res.sex="女";
    }
    count=(count+1)%2;
//   }
   }
 }
}
class Input extends Thread{
 Res res;
 public Input(Res res){
  this.res=res;
 }
 @Override
 public void run() {
  while (true){
//   synchronized (res.getClass()){
    System.out.println(res.username+","+res.sex);
//   }
  }
 }
}
public class OutInputThread {
 public static void main(String[] args) {
  Res res = new Res();
  Out out = new Out(res);
  Input input = new Input(res);
  out.start();
  input.start();
 }
}
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女

出现以上结果??消费者一直消费或者生产者一直生产

解决方法:生产者生产完成后消费者方可消费,否者不可消费,消费者未消费或者未消费完生产者不可生产,一次生产一次消费。其实也就是保证对res共享资源的操作同一时刻仅有同一个线程进行操作,

wait、notify、notifyAll方法

wait、notify、notifyAll是三个定义在Object类里的方法,可以用来控制线程的状态。

这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。

如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。当前线程从运行变为阻塞,释放所的资源

如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。让持有该锁的线程从阻塞态变为就绪。

如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

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

通过以下方式即可完成需求。

生产者获取res.getClass锁后,如果flag为true生产者通过调用res.getClass.wait进行等待,此时其他线程可获取该锁,如果flag为false,进行生产,然后设置flag为true保证资源消费后方可再生产,接着通过notify通知其他唤醒其他线程。

class Res{
 public String username;
 public String sex;
 //true 生产者等待,消费者可消费 false生产者可以生产,消费者不可消费
 public boolean flag=false;
}
class Out extends Thread{
 Res res;

 public Out(Res res){
  this.res=res;
 }
 @Override
 public void run() {
  //写操作
  int count=0;
  while (true){
   synchronized (res.getClass()){
    if(res.flag){
     try {
      res.getClass().wait();//让当前线程从运行变为阻塞,并且释放所的资源
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
    if(count==0){//偶数
     res.username="小明";
     res.sex="男";
    } else {//奇数
     res.username="小红";
     res.sex="女";
    }
    count=(count+1)%2;
    res.flag=true;
    res.getClass().notify();
   }
   }

 }
}
class Input extends Thread{
 Res res;
 public Input(Res res){
  this.res=res;
 }

 @Override
 public void run() {
  while (true){
   synchronized (res.getClass()){
    if(!res.flag){
     try {
      res.getClass().wait();
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
    System.out.println(res.username+","+res.sex);
    res.flag=false;
    res.getClass().notify();
   }
  }
 }
}
public class OutInputThread {
 public static void main(String[] args) {
  Res res = new Res();
  Out out = new Out(res);
  Input input = new Input(res);
  out.start();
  input.start();
 }
}

输出如下:

小明,男
小红,女
小明,男
小红,女
小明,男
小红,女
小明,男
小红,女

如果去掉notify会怎样?去掉一个?去掉两个?

去掉一个生产者可以打印多个(但是也不多),去掉消费者仅可打印一个,去掉两个可能不打印,也可能打印1个,所以wait、notify必须成对使用

wait(用于同步中)与sleep区别?

都是做休眠,wait需要notify

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

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

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

而当调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

总结

以上所述是小编给大家介绍的Java多线程通讯之wait,notify的区别详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • java多线程Thread-per-Message模式详解

    Thread-per-Message模式(这项工作就交给你了) 当你很忙碌的时候,这个时候公司楼下有个快递,于是你委托你的同事帮你拿一下你的快递,这样你就可以继续做自己的工作了 在Thread-Per-Message模式中,消息的委托端和执行端是不同的线程,消息的委托端会告诉执行端线程,这个工作就交给你了 Host类: 针对请求创建线程的类,主要通过开启新的线程,调用helper的handle,并将要打印的文字传递. public class Host { private final Helpe

  • Java使用Thread创建多线程并启动操作示例

    本文实例讲述了Java使用Thread创建多线程并启动操作.分享给大家供大家参考,具体如下: 按照教程实现了一个单线程的创建,但是单线程的创建于启动并不是很有实用价值的.毕竟直接在main方法中放着相关的执行操作本身也就是一种单线程的实现.接下来在之前用过的代码基础上稍作修改,形成如下代码: class ThreadDemo extends Thread { ThreadDemo(){}; ThreadDemo(String szName) { super(szName); } public v

  • Java多线程死锁示例

    本文实例演示了Java多线程死锁.分享给大家供大家参考,具体如下: package com.damlab.fz; public class DeadLock { public static void main(String[] args) { Resource r1 = new Resource(); Resource r2 = new Resource(); // 每个线程都拥有r1,r2两个对象 Thread myTh1 = new MyThread1(r1, r2); Thread myT

  • java模拟多线程http请求代码分享

    java模拟http发送请求,第一种是HttpURLConnection发送post请求,第二种是使用httpclient模拟post请求, 实例代码: package test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.Exec

  • java多线程开发之通过对战游戏学习CyclicBarrier

    CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,所有被屏障拦截的线程才会继续执行. 这篇文章将介绍CyclicBarrier这个同步工具类的以下几点 通过案例分析 两种不同构造函数测试 CyclicBarrier和CountDownLatch的区别 await方法及源码分析. 需求 继上一篇CountDo

  • Java基础之多线程

    线程中run()和start()的区别: 对于Thread对象来说,当你调用的是start(),线程会被放到等待队列,等待CPU调度,不一定马上执行:无需等待run()方法执行完毕,可以直接执行下面的代码: 而调用的是run()的话,就是当做普通的方法调用,程序还是要顺序执行的: 新建线程的几种方式: 实现Runnable接口:里面实现run()方法: 然后把这个实现了Runnable接口的类就新建为一个Thread t = new Thread(new (实现Runnable接口的类)),调用

  • 实例总结Java多线程编程的方法

    1.什么时候使用多线程编程 一个任务在正常情况下是按顺序执行的,但是如果当前任务里有多个相似进程块(例如for,while语句),我们就可以考虑把这些代码块抽出来并行运行,无需阻塞 2.实现多线程的几种方式 一种是继承Thread类重写run方法,另一种是实现Runnable接口重写run方法 启动多线程很多情况下是为了处理并发进程,此时对于部分实时性要求不是那么高的业务需求,我们还可以通过实现队列的方式,异步实现. 3.举例 继承Thread /** * * @ClassName: Threa

  • Java多线程之Callable接口的实现

    1.接口的定义: public interface Callable<V> { V call() throws Exception; } 2.Callable和Runnable的异同 先看下Runnable接口的定义 public interface Runnable { public abstract void run(); } Callable的call()方法类似于Runnable接口中run()方法,都定义任务要完成的工作,实现这两个接口时要分别重写这两个方法,主要的不同之处是call

  • Java多线程通讯之wait,notify的区别详解

    下面通过代码给大家介绍java多线程通讯之wait notify的区别,具体内容如下所示: class Res{ public String username; public String sex; } class Out extends Thread{ Res res; public Out(Res res){ this.res=res; } @Override public void run() { //写操作 int count=0; while (true){ // synchroniz

  • java线程中start和run的区别详解

    这篇文章主要介绍了java线程中start和run的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 public class Test1 extends Thread { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName()); } } public static void main(String[

  • java中String StringBuffer和StringBuilder的区别详解

    目录 从声明定义上来谈 从结构上来谈 从线程安全来谈 总结 从声明定义上来谈 只有String 可以 直接声明创建 而 StringBuffer 与 StringBuilder 必须去new对象 这是因为只有String会在这种声明方式下去字符串常量池创建,其他则没有 StringBuffer stf = new StringBuffer("abc"); StringBuilder stb = new StringBuilder("abc"); StringBuff

  • Java Thread.currentThread().getName() 和 this.getName()区别详解

    目录 currentThread的详解 为什么为main呢? 创建一个新的线程 如何理解上述的情况呢? 为什么新线程的名字为thread0呢? 再看一种带this的情况 创建的线程setName的情况 总结 currentThread的详解 currentThread方法是Thread类的一个静态方法,用来获取当前运行的代码段,正在被哪个线程调用.我们先来看一眼源码. 是一个native方法.直接与系统层面做交互.下面看一段代码 public static void main(String[]

  • java中的i++和++i的区别详解

    java中的前加加++和后加加++,有很多人搞的很晕,不太明白!今天我举几个例子说明下前++和后++的区别! 其实大家只要记住一句话就可以了,前++是先自加再使用而后++是先使用再自加! 前++和后++总结:其实大家只要记住一句话就可以了,前++是先自加再使用而后++是先使用再自加! 请大家看下面的例子就明白了! public class Test { public static void main(String[] args) { //测试,前加加和后加加 //前++和后++总结:其实大家只要

  • 在C#和Java语言中for和foreach的区别详解

    for循环和foreach循环的区别 首先在这里声明一点,C#和Java这两种语言很相似,尤其是初学的数据类型那一部分,所以这里写的for和foreach的区别在C#和Java中都适用. 我会在下面分别列出两种语言的for和foreach分别循环打印一个数组,大家可以看看区别 话不多说,直接上代码: //c# //先创建一个数组 int[] arr = new int[3] {99, 11, 22}; //利用for循环打印(可以创建一个变量 i;判断这个i是否小于数组的长度;每次循环i自增1)

  • Java多线程之线程池七个参数详解

    ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交.线程管理.监控等方法. 下面是ThreadPoolExecutor类的构造方法源码,其他创建线程池的方法最终都会导向这个构造方法,共有7个参数:corePoolSize.maximumPoolSize.keepAliveTime.unit.workQueue.threadFactory.handler. public ThreadPoolExecutor(int corePoolS

  • Java中Validated、Valid 、Validator区别详解

    目录 1. 结论先出 JSR 380 Valid VS Validated 不同点? Validator 2. @Valid和​​​​​​​@Validated 注解 3. 例子 4.使用@Valid嵌套校验 5. 组合使用@Valid和@Validated 进行集合校验 6. 自定义校验 自定义约束注解 工作原理 结论 参考链接: 1. 结论先出 Valid VS Validated 相同点 都可以对方法和参数进行校验 @Valid和@Validated 两种注释都会导致应用标准Bean验证.

  • Java多线程开发工具之CompletableFuture的应用详解

    做Java编程,难免会遇到多线程的开发,但是JDK8这个CompletableFuture类很多开发者目前还没听说过,但是这个类实在是太好用了,了解它的一些用法后相信你会对它爱不释手(呸渣男,咋对谁都爱不释手呢),好了我先简单举个列子,告诉你用它有多好.Single Dog拿一个Appointment来举个列子,如下: /** * 女神化完妆之后,还需要一小会选衣服,不过分吧. * 也就是说我们现在有2个异步任务,第一个是化妆,第二个是选衣服. * 选衣服要在化妆完成之后进行,这两个任务是串行

  • Java多线程中线程间的通信实例详解

    Java多线程中线程间的通信 一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.util.List; public class MyList { private volatile static List list = new ArrayList(); public void add() { list.add("apple"); } publ

随机推荐