Java学习笔记16

Object类是所有类、数组、枚举类的父类,是类层次结构的根类。每个类都使用Object作为超类。所有对象(包括

数组)都实现这个类的方法。

Object类实现了以下方法:

现在我们看看源码中notify()、notifyAll()、wait(long)、wait(long,int)、wait()是如何定义的:

(1)notify():

public final native void notify();

(2)notifyAll():

 public final native void notifyAll();

(3)wait(long):

public final native void wait(long timeout) throws InterruptedException;

(4)wait(long,int):

 public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
            timeout++;
        }

        wait(timeout);
    }

(5)wait():

 public final void wait() throws InterruptedException {
        wait(0);
    }

(1)notify()的方法说明:

唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任

意性的,并在对实现做出决定时发生。线程通过调用其中一个wait 方法,在对象的监视器上等待。

直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同

步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所

有者:

  • 通过执行此对象的同步实例方法。
  • 通过执行在此对象上进行同步的 synchronized 语句的正文。
  • 对于 Class 类型的对象,可以通过执行该类的同步静态方法。

一次只能有一个线程拥有对象的监视器。

(2)notifyAll()的方法说明:

唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。

直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同

步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。有关线程能够成为监视器所有者的方法的描述,请参阅

notify 方法。


(3)wait(long)的方法说明:

在其他线程调用此对象的notify() 方法或
notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。

当前线程必须拥有此对象监视器。

此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调

度目的,在发生以下四种情况之一前,线程 T 被禁用,且处于休眠状态:

  • 其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
  • 其他某个线程调用此对象的 notifyAll 方法。
  • 其他某个线程中断线程 T
  • 大约已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待。

然后,从对象的等待集中删除线程 T,并重新进行线程调度。然后,该线程以常规方式与其他线程竞争,以获得在该

对象上同步的权利;一旦获得对该对象的控制权,该对象上的所有其同步声明都将被恢复到以前的状态,这就是调

wait 方法时的情况。然后,线程
Twait 方法的调用中返回。所以,从 wait 方法返回时,该对象和线程T 的同

步状态与调用wait 方法时的情况完全相同。

在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种情况在实

践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不

满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
     }

(4)wait(long,int)的方法说明:

在其他线程调用此对象的 notify() 方法或notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际

时间量前,导致当前线程等待。

此方法类似于一个参数的 wait 方法,但它允许更好地控制在放弃之前等待通知的时间量。用毫微秒度量的实际时间

量可以通过以下公式计算出来:

1000000*timeout+nanos

在其他所有方面,此方法执行的操作与带有一个参数的 wait(long) 方法相同。需要特别指出的是,wait(0, 0)

wait(0) 相同。

当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权,并等待下面两个条件之一发生:

  • 其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。
  • timeout 毫秒值与 nanos 毫微秒参数值之和指定的超时时间已用完。

然后,该线程等到重新获得对监视器的所有权后才能继续执行。

对于某一个参数的版本,实现中断和虚假唤醒是有可能的,并且此方法应始终在循环中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout, nanos);
... // Perform action appropriate to condition
     }
 

此方法只应由作为此对象监视器的所有者的线程来调用。有关线程能够成为监视器所有者的方法的描述,请参阅

notify 方法。

(5)wait()的方法说明:

在其他线程调用此对象的notify() 方法或
notifyAll() 方法前,导致当前线程等待。换句话说,此方法的行为就好像

它仅执行wait(0) 调用一样。

当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或

notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续

执行。

对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
     }
 

此方法只应由作为此对象监视器的所有者的线程来调用。有关线程能够成为监视器所有者的方法的描述,请参阅

notify 方法。

在上面源码中关于wait(long,int)方法的实现方式。可以看出,此方法中的nanos毫微秒,只能精确到毫秒。而且这几

个方法都是由Object来实现的,也就是每个对象都有锁。

以上只是这几个方法的说明,在讲到后面的多线程时再深入举例。

转载请注明出处:http://blog.csdn.net/hai_qing_xu_kong/article/details/43917141   情绪控_

时间: 2024-10-14 03:10:47

Java学习笔记16的相关文章

我的java学习笔记(16)关于对象克隆与调回

1.当拷贝一个变量时,原始变量与拷贝变量引用同一个对象,改变一个变量所引用的对象将会对另一个变量产生影响. a a1 = new a(); a a2 = a1; a2.up(10);//a1也会改变 2.如果创建一个对象的新的copy,它的状态与原来的对象一样,但以后可以各自改变各自的状态,那就需要使用clone方法. a a1 = new a(); a a2 = a1.clone(); a2.up(10);//a1不会改变了 3.如果对象中的所有数据域都属于数值或基本类型,这样的拷贝域没有任何

我的java学习笔记(16)关于内部类(part 1)

1.内部类是定义在另一个类中的类. 原因:a.内部类方法可以访问类定义所在的作用域中的数据,包括私有的数据. b.内部类可以对同一个包中的其他类隐藏起来. c.当想要定义一个回调函数且不想编写大量的代码时,使用匿名内部类比较便捷. 2.内部类皆可以访问自身的数据域,也可以访问创建它的外围类对象的数据域. 3.内部类的对象总有一个隐式引用,它指向了创建它的外部类对象.这个引用在内部类的定义中是不可见的. 4.外围类的设置一般都在内部类的构造器中设置. 5.只用内部类可以是私有类,而常规类只可以具有

Java学习笔记16(面向对象九:补充内容)

总是看到四种权限,这里做一个介绍: 最大权限是public,后面依次是protected,default,private private修饰的只在本类可以使用 public是最大权限,可以跨包使用,不同包的子类和无关类都可以使用,可以修饰类,方法,成员变量 不写权限就是default默认权限:限于本包内使用 protected权限:跨包后的类如果有继承关系(子类),不能使用default修饰的,而可以使用protected修饰的,调用时候必须在子类的里面才可以调用父类的受保护权限,注意prote

java学习笔记3——java关键字

java学习笔记3——java关键字 虽然老师说不用刻意的去记忆,但是我还是在网上找到了非常详细的注解,再次收藏 关键字的类型表: 各个关键字的详细注解和实例,按首字母排序: 1.abstract abstract 关键字可以修改类或方法. abstract 类可以扩展(增加子类),但不能直接实例化. abstract 方法不在声明它的类中实现,但必须在某个子类中重写. -示例- public abstract class MyClass{ } public abstract String my

【Java学习笔记之二十六】深入理解Java匿名内部类

在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始化匿名内部类.匿名内部类使用的形参为何要为final. 一.使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: new 父类构造器(参数列表)|实现接口() { //匿名内部类的类体部分 } 在这里我们看到使用匿名内部类我们必须要继承一个父类或者

Java学习笔记之继承

一.继承的基础 在Java术语中,被继承的类叫超类(superclass),继承超类的类叫子类(subclass). 举例说明: 1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重载构造方法 8 public Box(Box ob) 9 { 10 width = ob.width; 11 height = ob.height; 12 depth = ob.dep

Java学习笔记之接口

一.接口的概念与定义 首先考虑一个简单的接口的定义: public interface Output { int MAX_LINE = 40; void out(); void getData(String msg); } 定义接口使用关键字interface 修饰符interface前面的public可以省略,如果省略,则采用默认访问控制,即只有在相同包结构的代码才可以访问此接口 接口不可以有构造方法(区别于类中的构造方法) 接口里面的所有成员,包括常量.方法等都是public访问权限,所以在

java学习笔记07--日期操作类

java学习笔记07--日期操作类 一.Date类 在java.util包中定义了Date类,Date类本身使用非常简单,直接输出其实例化对象即可. [java] view plaincopy public class T { public static void main(String[] args) { Date date  = new Date(); System.out.println("当前日期:"+date); //当前日期:Thu May 16 23:00:57 CST 

Java 学习笔记(2015.7.20~24)

Java 学习笔记(2015.7.20~24) Java Java 学习笔记(2015.7.20~24) 1.StringBuffer与StringBuilder的区别: 2.基本数据类型包装类 3.Date.Calendar.DateFormat等与时间相关的类 1.常用类String 2.正则表达式 3.常用类 StringBuffer 代表可变的字符序列 拆箱与装箱 包装类的应用 匿名内部类 数组 day11 day12 day13 day14 day11 父类中使用public定义的方法