jvm多个线程间的通信是通过 线程的锁、条件语句、以及wait()、notify()/notifyAll组成。

下面来实现一个启用多个线程来循环的输出两个不同的语句。

package com.app.thread;

import javax.swing.plaf.SliderUI;
/**
 * 看出问题来
 * @author Gordon
 *
 */
public class LockDemo {
 public static void main(String[] args) {
//  System.out.println("lock");

final OutTurn ot = new OutTurn();
  
  for(int j=0;j<100;j++){

new Thread(new Runnable() {

public void run() {
//     try {
//      Thread.sleep(10);
//     } catch (InterruptedException e) {
//      e.printStackTrace();
//     }
     for (int i = 0; i <5; i++) {     
      ot.sub();
     }
    }
   }).start();

new Thread(new Runnable() {

public void run() {
//     try {
//      Thread.sleep(10);
//     } catch (InterruptedException e) {
//      e.printStackTrace();
//     }
     for (int i = 0; i < 5; i++) {     
      ot.main();
     }
    }
   }).start();
  }

}
}

class OutTurn {
 private boolean isSub = true;
 private int count=0;

public synchronized void sub() {
  try {
   while (!isSub) {
    this.wait();
   }
   System.out.println("sub ---- "+count);
   isSub=false;
   this.notify();
  } catch (Exception e) {
   e.printStackTrace();
  }
  count++;

}

public synchronized void main() {
  try {
   while(isSub){
    this.wait();
   }
   System.out.println("main (((((((((((( "+count);
   isSub=true;
   this.notify();
  } catch (Exception e) {
   e.printStackTrace();
  }
  count++;
 }
}

不知能否看出问题,第一次写的时候出现了问题,找了很久才找了出来,一直以来是没有注意notify与notifyAll()的使用,在此酿成大错,哎。。。

说明一下notify与notifyAll的区别:

  以上sub和main方法都是用了锁,所以说多个调用sub方法的线程和多个调用main方法的都会处于阻塞状态,都会等待一个正在运行的其他线程来唤醒他们,以上代码使用了notify进行唤醒,notify只能唤醒一个线程,其他等待的线程仍然处于wait状态,如果调用sub方法的线程执行完后,所有的线程都处于等待状态,isSub=false了,这时唤醒的是一个sub方法调度线程,那么while循环等于true,则该线程也会处于等待状态,之后所有的线程处于等待状态,没有运行的线程来唤醒他们,这时就产生了死锁。如果使用notifyAll()来唤醒所有正在等待该锁的线程,那么所有的线程都会处于运行前的准备状态,就是sub方法执行完后,唤醒了所有等待该锁的状态,那么即使再次唤醒一个sub方法调度线程,那么该线程再次处于等待状态后,还有其他的线程可以获得该锁,进入运行状态。所以notify方法很容易引起死锁,除非你根据自己的程序设计,确定不会引起死锁,notifyAll则是线程的安全唤醒方法。

言归正传,以上代码 只需要将sub和main方法中的参数改成this.notifyAll()即可。

java 线程之间通信以及notify与notifyAll区别。的更多相关文章

  1. Java线程之间通信

    用多线程的目的:更好的利用CPU的资源.因为所有的多线程代码都可以用单线程来实现. 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程. 并行:多个CPU实例或者多台机器同时执行一段处理逻辑, ...

  2. java 线程之间的协作 wait()与notifyAll()

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmdydWkxOTg4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  3. 如何在 Java 中正确使用 wait, notify 和 notifyAll(转)

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...

  4. 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...

  5. Java线程间通信-回调的实现方式

    Java线程间通信-回调的实现方式   Java线程间通信是非常复杂的问题的.线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互.   比如举一个简单例子,有一个多线程的 ...

  6. (转载) Android两个子线程之间通信

    Android两个子线程之间通信 标签: classthreadandroid子线程通信 2015-03-20 17:03 3239人阅读 评论(0) 收藏 举报  分类: 个人杂谈 版权声明:本文为 ...

  7. 关于CPU核心,线程,进程,并发,并行,及java线程之间的关系

    前言:作为一个转行java的小白,一直搞不清楚java中的多线程.于是来梳理一下关于CPU核心,线程,进程,并发,并行,及java线程之间的关系, 1.CPU角度来看: 我们以Intel的Core i ...

  8. Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.我们来看下相关定义: w ...

  9. java线程之间的通信

    1.常用的方法 sleep() 该线程进入等待状态,不释放锁 wait() 该线程进入等待状态,释放锁 notify() 随机唤醒一个线程 notifyAll() 唤醒全部线程 getName() 获 ...

随机推荐

  1. Android学习总结——获取被启动的Activity传回的数据

    当前Activity:包含一个Button和一个TextView,用于启动另一个Activity和显示传回的数据,这里重写了onActivityResult()方法. public class Mai ...

  2. Zipper

      Zipper Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  3. paip.svn使用最佳实践

    paip.svn使用最佳实践 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net/attilax 1 ...

  4. A Game with Colored Balls

    题目链接 题意: 给一个长度为n的字符串,每次删除字母同样切连续的串,假设有多个,删除最左边的.最长的串.每次删除输出串的字母,每一个字母的下标(1-n) N (1 ≤ N ≤ 106),串仅仅包含r ...

  5. TreeView(C#)无限目录树代码片段

    #region 绑定客户树 protected void bindTreeView() { TreeView1.Nodes.Clear(); string userid = Session[" ...

  6. Flash Recovery Area

    1. 设置闪回恢复区 闪回恢复区主要通过3个初始化参数来设置和管理 db_recovery_file_dest:指定闪回恢复区的位置db_recovery_file_dest_size:指定闪回恢复区 ...

  7. Python基础之 urllib模块urlopen()与urlretrieve()的使用方法详解。

    Python urllib模块urlopen()与urlretrieve()的使用方法详解   1.urlopen()方法urllib.urlopen(url[, data[, proxies]]) ...

  8. C++_String

    String -String的实现 -String常用操作

  9. Python学习笔记(四)Python函数的参数

    Python的函数除了正常使用的必选参数外,还可以使用默认参数.可变参数和关键字参数. 默认参数 基本使用 默认参数就是可以给特定的参数设置一个默认值,调用函数时,有默认值得参数可以不进行赋值,如: ...

  10. 用正则表达式抓取网页中的ul 和 li标签中最终的值!

                获取你要抓取的页面 const string URL = "http://www.hn3ddf.gov.cn/price/GetList.html?pageno=1& ...