zoukankan      html  css  js  c++  java
  • java 线程之间通信以及notify与notifyAll区别。

     

    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()即可。

  • 相关阅读:
    Web Browser使用技巧
    Excel 函数
    删除文件夹, 解决源文件名长度大于文件系统支持的长度问题
    Send Mail using C# code
    动态规划——最长回文子串
    字符串处理总结
    打印日期
    A+B
    对称矩阵
    最小年龄的3个职工
  • 原文地址:https://www.cnblogs.com/chengpeng15/p/5814202.html
Copyright © 2011-2022 走看看