wait() notify() notifyAll()

  • wait和notify方法必须写在synchronized方法内,即在调用wait和notify方法前,需先获得对象锁;
  • 调用wait方法则释放锁;wait方法返回后,需获得对象锁才可继续执行下面语句;
  • 多个线程wait时,若另外的线程调用notify方法后,由JVM决定唤醒其中一个线程;
  • 多个线程wait时,若另外的线程调用notifyAll方法,则唤醒所有wait线程,但是只有其中一个线程可以获得对象锁,执行wait下面的语句,其余的等待释放对象锁后才可执行;
  • 调用notify/notifyAll时,线程并没有释放对象锁,只是其余线程被唤醒,但仍无法执行,只有等调用完notify/notifyAll并退出synchronized块,释放对象锁后,其余线程中的一个才可获得锁执行。
wait(),notify()/notityAll()方法是普通对象的方法(Object超类中实现),而不是线程对象的方法]

[wait(),notify()/notityAll()方法只能在同步方法中调用]


===================================================
sleep()


另:sleep方法使当前线程暂停执行一段时间,从而让其他线程有机会继续执行,但它并不释放对象锁。也就是说,如果有Synchronized块,其他线程仍然不能访问共享数据。

举生产者-消费者例子来说:仓库提供两个同步方法,一个put,一个get,假设put方法中线程sleep30秒,在这段时间中,get方法并不能从仓库中获取产品,因为sleep时并没有释放对象锁,所以调用get方法的线程不能执行。

假设有两个线程同时执行,都没有调用synchronized方法,一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有sleep()方法,只有高优先级的线程执行完成后,低优先级的线程才能执行;但当高优先级的线程sleep(5000)后,低优先级就有机会执行了。

即:sleep方法可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程获得执行的机会。

===================================================
wait() 区别 sleep()

1、这两个方法来自不同的类分别是,

sleep()来自Thread类,

wait()来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

2、最主要

sleep方法没有释放锁

而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用


synchronized(x){

x.notify()

//或者wait()

}

4、sleep必须捕获异常

而wait,notify和notifyAll不需要捕获异常

===================================================

[synchornized方法]



  如果一个方法声明为synchornized的,则等同于在这个方法上调用synchornized(this).



  如果一个静态方法被声明为synchornized,则等同于在这个方法上调用synchornized(类.class).

现在进入wait方法和notify/notifyAll方法.这两个(或叫三个)方法都是Object对象的方法,而不是线程对象的方法.如同锁一样,它们是在线程中调用某一对象上执行的.

  class Test{

    public synchornized void test(){

    //获取条件,int x 要求大于100;

    

        if(x < 100)   // 最好使用while(x<100)

          wait();    //即 this.wait()

    }

  }



  这里为了说明方法没有加在try{}catch(){}中,如果没有明确在哪个对象上调用wait()方法,则为this.wait();

假如:

Test t = new Test();

现在有两个线程都执行到t.test();方法.其中线程A获取了t的对象锁,进入test()方法内.这时x小于100,所以线程A进入等待.

当一个线程调用了wait方法后,这个线程就进入了这个对象的休息室(waitset),这是一个虚拟的对象,但JVM中一定存在这样的一个数据结构用来记录当前对象中有哪些程线程在等待.



  当一个线程进入等待时,它就会释放锁,让其它线程来获取这个锁.



 线程A运行到this.wait(),  所以线程B有机会获得了线程A释放的锁,进入test()方法,如果这时x还是小于100,线程B也进入了t的休息室.这两个线程只能等待其它线程调用notity[All]来唤醒.



  但是如果调用的是有参数的wait(time)方法,则线程A,B都会在休息室中等待这个时间后自动唤醒.







  [为什么真正的应用都是用while(条件)而不用if(条件)]

  在实际的编程中我们看到大量的例子都是用     

        while(x < 100)

          wait();

go();而不是用if,为什么呢?

  在多个线程同时执行时,if(x <100)是不安全的.因为如果线程A和线程B都在t的休息室中等待,

这时另一个线程使x==100了,并调用notifyAll方法,线程A继续执行下面的go().而它执行完成后,x有可能又小于100,比如下面的程序中调用了--x,这时切换到线程B,线程B没有继续判断,直接执行go();就产生一个

错误的条件,只有while才能保证线程B又继续检查一次.

  



  [notify/notifyAll方法]

  这两个方法都是把某个对象在休息区内的线程唤醒, notify只能唤醒一个,但究竟是哪一个不能确定,而notifyAll则唤醒这个对象上的休息室中所有的线程.

  一般为了安全性,我们在绝对多数时候应该使用notifiAll(),  除非你明确知道只唤醒其中的一个线程.

那么是否是只要调用一个对象的wait()方法,当前线程就进入了这个对象的休息室呢?

事实中,要调用一个对象的wait()方法,只有当前线程获取了这个对象的锁 ,   换句话说一定要在这个对象的同步方法 或
以这个对象为参数的同步块中.

class MyThread extends Thread{

Test t = new Test();

  public void run(){

    t.test();

    System.out.println("Thread say:Hello,World!");

  }

}







public class Test {

  int x = 0;

  public void test(){

    if(x==0)

    try{

      wait();   // 即this.wait()     wait()要放到同步代码块里面

}

catch(Exception e){}

}

  public static void main(String[] args) throws Exception{

    new MyThread().start();

  }

}



这个线程就不会进入t的wait方法而直接打印出Thread say:Hello,World!.

而如果改成:

public class Test {



  int x = 0;

  public synchornized void test(){

    if(x==0)

    try{

      wait();

    }catch(Exception e){}

  }

  public static void main(String[] args) throws Exception{

    new MyThread().start();

  }

}

我们就可以看到线程一直等待,   注意这个线程进入等待后没有其它线程唤醒,   除非强行退出JVM环境,否则它一直等待.







所以请记住:

1,线程要想调用一个对象的wait()方法就要先获得该对象的监视锁,而一旦调用wait()后又立即释放该锁



2,如果要把notify/notifyAll和wait方法放在一起用的话,必须先调用notify/notifyAll后调用wait,因为如果调用完wait,该线程就已 

经不是current thread了



3,wait(),notify(),notifyAll()方法必须出现在同步方法或同步代码块中

wait() 区别 sleep()的更多相关文章

  1. c#与java的区别

    经常有人问这种问题,用了些时间java之后,发现这俩玩意除了一小部分壳子长的还有能稍微凑合上,基本上没什么相似之处,可以说也就是马甲层面上的相似吧,还是比较短的马甲... 一般C#多用于业务系统的开发 ...

  2. jquery和Js的区别和基础操作

    jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...

  3. 【原】nodejs全局安装和本地安装的区别

    来微信支付有2年多了,从2年前的互联网模式转变为O2O模式,主要的场景是跟线下的商户去打交道,不像以往的互联网模式,有产品经理提需求,我们帮忙去解决问题. 转型后是这样的,团队成员更多需要去寻找业务的 ...

  4. 探究@property申明对象属性时copy与strong的区别

    一.问题来源 一直没有搞清楚NSString.NSArray.NSDictionary--属性描述关键字copy和strong的区别,看别人的项目中属性定义有的用copy,有的用strong.自己在开 ...

  5. X86和X86_64和X64有什么区别?

    x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...

  6. Java中Comparable与Comparator的区别

    相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...

  7. MySQL中interactive_timeout和wait_timeout的区别

    在用mysql客户端对数据库进行操作时,打开终端窗口,如果一段时间没有操作,再次操作时,常常会报如下错误: ERROR (HY000): Lost connection to MySQL server ...

  8. 设置line-height:1.5和line-height:150%或者line-height:150px的区别

    直接正题: 看一下line-height可能的值: 其实可以分为两类: (1)不带单位的(如line-height:1.5),这种是推荐使用的: (2)带单位的(如line-heigth:30px/1 ...

  9. C#中Length和Count的区别(个人观点)

    这篇文章将会很短...短到比你的JJ还短,当然开玩笑了.网上有说过Length和count的区别,都是很含糊的,我没有发现有 文章说得比较透彻的,所以,虽然这篇文章很短,我还是希望能留在首页,听听大家 ...

  10. select、poll、epoll之间的区别总结

    select.poll.epoll之间的区别总结 05/05. 2014 select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪 ...

随机推荐

  1. Bootstrap多层模态框modal嵌套问题

    一.问题 在项目里忽然新加了一个需求,在原本弹出的模态框里,点击模态框里面的按钮再弹出一个模态框,出来另个模态框来展示详细信息.此时就存在两个模态框在这个需求没加之前有一个弹出的模态框也是需要继续点击 ...

  2. python 设计模式之观察者模式

    观察者模式是一个软件设计模式,一个主题对象博包涵一系列依赖他的观察者,自动通知观察者的主题对象的改变,通常会调用每个观察者的一个方法.这个设计模式非常适用于分布式事件处理系统. 典型的在观察者模式下: ...

  3. gradients的一些注意点

    Each variable has a [.grad_fn] attribute that references a Function that has created the Variable(ex ...

  4. 基于WPF系统框架设计(5)-Ribbon整合Avalondock 2.0实现多文档界面设计(二)

    AvalonDock 是一个.NET库,用于在停靠模式布局(docking)中排列一系列WPF/WinForm控件.最新发布的版本原生支持MVVM框架.Aero Snap特效并具有更好的性能. Ava ...

  5. mysql----乐观锁总结和实践

    悲观锁并不是适用于任何场景,它也有它存在的一些不足,因为悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性.如果加锁的时间过长,其他用户长时间无法访问,影响了程序的并发访问性,同时这 ...

  6. yield理解

    http://www.jianshu.com/p/d09778f4e055 从yield处返回一个值,下次从yield后开始执行

  7. php 报错等级

    定义和用法:    error_reporting() 设置 PHP 的报错级别并返回当前级别. 函数语法:    error_reporting(report_level) 如果参数 level 未 ...

  8. python测试网络可达性的方法

    1.ping连通性测试 #!/usr/bin/env python #-*- coding: utf-8 -*- import os,sys,re import subprocess def NetC ...

  9. C#面试基础题1

    1.简述 private. protected. public. internal 修饰符的访问权限.(C++中没有internal) private : 私有成员, 在类的内部才可以访问 ,也就是类 ...

  10. 126. Word Ladder II(hard)

    126. Word Ladder II 题目 Given two words (beginWord and endWord), and a dictionary's word list, find a ...