zoukankan      html  css  js  c++  java
  • 关于notify() 和notifyAll() 一个需要注意的地方

    notify() 和 notifyAll()都是唤醒其他正在等待同一个对象锁的线程。

    下面是我遇到的一个问题,记下来,免得忘了。

    直接上代码,有错误的代码:

    代码描述:有一个Caculate类,类中又一个成员变量 j,现在有多个线程对这个变量进行操作。一个增加操作、一个减少操作。增加操作:当 j = 0 时,j++ 。减少操作:当 j = 1 时,j-- 。这两个操作分别对应这 add()方法 和sub()方法,都使用synchronized关键字。

    可以直接复制拿来运行一下

    package com.zcd2;
    
    public class ThreadTest1
    {
        public static void main(String[] args)
        {
            Caculate caculate = new Caculate();
            
            //使用多个线程对实例caculate进行增加操作。
            for(int i = 0; i < 10; i++)
            {
                Thread1 t = new Thread1(caculate);
                t.start();
            }
            
            //使用多个线程对实例caculate进行减少操作。
            for(int i = 0; i < 2; i++)
            {
                Thread2 t = new Thread2(caculate);
                t.start();
            }
        }
    }
    
    //Thread1线程进行增加操作
    class Thread1 extends Thread
    {
        private Caculate caculate;
        
        public Thread1()
        {
            
        }    
        
        public Thread1(Caculate caculate)
        {
            this.caculate = caculate;
        }
        
        @Override
        public void run()
        {
            int i = 0;
    
            //死循环,手动停止
            while(true)
            {
                try
                {
                    caculate.add();
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                i++;
                System.out.println("加线程执行第 " + i + " 次");
            }
        }    
    }
    
    //Thread2进行减少操作。
    class Thread2 extends Thread
    {    
        private Caculate caculate;
        
        public Thread2()
        {
        }
    
        public Thread2(Caculate caculate)
        {
            this.caculate = caculate;
        }
    
        @Override
        public void run()
        {    
            int i = 0;
            
            //死循环,手动停止
            while(true)
            {
                try
                {
                    caculate.sub();
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                i++;
                System.out.println("减线程执行第 " + i + " 次");
            }
        }    
    }
    
    //
    class Caculate
    {
        private int j = 0;    
    
        //增加操作
        public synchronized void add() throws InterruptedException
        {
         //当 j = 1 的时候说明不符合操作条件,要放弃对象锁。
            while(j == 1)
            {
                wait();
                System.out.println();
            }    
            j++;
            System.out.println(j);
            notify();
        }
    
        //减少操作
        public synchronized void sub() throws InterruptedException
        {
         //当j = 0 的时候说明不符合操作条件,放弃对象锁
            while(j == 0)
            {
                wait();
                System.out.println();
            }
            j--;
            System.out.println(j);
            notify();
        }
    }

    以上代码并不能一直循环执行,按道理说应该是一直循环执行的。

    为什么呢????????

    这就涉及到了notify() 和 notifyAll()的其中一个区别了。

    这个区别就是:调用 notify() 方法只能随机唤醒一个线程,调用notifyAll() 方法的唤醒所有的等待的线程。

    比如这里,当一个线程在正常执行。。。假设这里正常执行完一个增加操作的线程,然后调用 notify() 方法 那么它会随机唤醒一个线程。

      ①、如果唤醒的是进行减少操作的线程,此时 j = 1,线程能够正常执行减少操作。

      ②、如果唤醒的是进行增加操作的线程,此时 j = 1,那么不符合增加操作的条件,他就会调用 wait() 方法。那么调用完wait()方法后程序就会发现已经没有被唤醒的线程了。唯一一个被唤醒的线程因不符合条件放弃了对象锁,其他线程又没有被唤醒。此时程序只能一直等到其他线程被唤醒,但是它等不到了。

    解决:

    把notify() 改成notifyAll() 这个问题就解决了。因为如果唤醒一个线程,但是这个线程因不符合执行条件而放弃对象,还有很多唤醒的线程。

    所以,当多个(两个以上的)线程操作同一个对象的时候最好使用的notifyAll(),这样就不会出现上述的问题了。


    发现一个问题,既然使用notify()会出问题那为什么不在每个地方的使用notifyAll()呢??这二者还有其他我没了解的区别吗???难道使用notifyAll() 会使性能大大下降???有待解决。

  • 相关阅读:
    Appium
    iOS 定位方式 iOSNsPredicateString 详解
    Appium 遇到 Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65 的解决方法
    自动化工具 appium 在真机上测试的配置 (使用个人 Apple ID)
    查看iOS App的bundleId
    阿里巴巴热招求推荐求转发
    一文读懂网络协议
    Idea生成Javadoc
    系统监控
    Hystrix使用详解
  • 原文地址:https://www.cnblogs.com/GooPolaris/p/7920343.html
Copyright © 2011-2022 走看看