JAVA多线程的理解wait、notify、notifyAll

来源:互联网 发布:政务数据管理制度 编辑:程序博客网 时间:2024/05/29 06:37

 身为一个初级的web小猿猴来说,对于Java多线程的知识,还难以有独到的见解和理论,在这里,只是把自己的一些心得分享出来,希望隐藏在csdn中的大牛们,可以浮出水面,不吝赐教。


          在多次的面试中,都难逃java面试官的追问:“你对java多线程的理解是什么?什么是同步、什么是异步,wait、notify、notifyAll的用法。"在这里,我尽可能的用自己的语言,描述下,我对wait、notify、notifyAll的理解,进行一个简单的讲述。

         首先,在试用wait、notify、notifyAll时,在其方法中,必须有synchronized方法体,或者这个方法本身就标注着为synchronized。否则,系统则会抛出一个java.lang.IllegalMonitorStateException异常。

    那么synchronized的含义是什么呢。没错,是锁的概念,或者可以理解为,标记为synchronized的方法,或者方法中加入synchronized的块,那么这段表达,将变成一座独木桥,一次只能有一个人通过,其他人,就在一旁呐喊助威好了,当我通过以后,你们在一个个的像我一样走过来吧。

       如何对方法体或者或者方法体中加入的方法块加入“锁”这个概念,通常在多个线程访问同一个资源的时候,只有当他们的对象是同一个对象时,锁的概念,才能体现出来(静态的方法除外,静态方法,输入类方法,那么锁定的将会是这个类本身,因为静态方法,就是共享资源),再加入synchronized字段之前,我们所访问的资源,可以说是异步的。举一个例子,我在澡堂内洗澡,这个时候,你进来了,你也在澡堂内洗澡,其他的人进来了,也是如此,那么,澡堂这个资源,就是未加synchronized时的资源状态。同里,如果方法体中,加入了synchronized字段,那么,公共厕所就变成了家里的卫生间,在我洗澡的时候,会对卫生间的门“锁上”,我可不想让那个冒失得人,看到我裸体的样子,那么,其他的人,在想进入卫生间,只有当我使用完成以后,下一个人才可以进去。这就是所谓的同步

         需要记住的是synchronized是访问的同一个资源下才可以使用,那么加入synchronized将没有任何意义,因为,我们进入的不是同一个卫生间,那么我锁不锁门,都和你们没有任何关系。同时,需要注意的是,在一个类中,有多个synchronized方法,那么一次只能执行一个方法,在其他用户访问其他synchronized方法时,依然将会是等待中。可以理解为,我在卫生间中洗澡,你想去卫生间小便、洗手、或者干其他事情,无论你要什么,我都不会让你进去的。

        wait——让出资源,进入睡眠,等待被唤醒,醒来后,继续执行接下来的工作。
       notify——唤醒一个进入睡眠的线程。
       notifyAll——唤醒所有的睡眠中的线程。

       那么,现在引用一个例子来进行讲解。
   package com.jbp.util;

public class Titket {


//初始化票据
private int titketNum;

public Titket(int titketNum){
this.titketNum=titketNum;
}

/**
* 添加发型票据
* @param titketNumAdd
*/
public void putTitket(int titketNumAdd){
if(this.titketNum>=60){
synchronized (this) {
System.out.println("票据充足,开始售票");
this.notifyAll(); //当票据大于60张时,唤醒所有线程
}
}
this.titketNum+=titketNumAdd;
}

/**
* 售票功能
* @param titKetNumRemove
*/
public synchronized void getTitket(int titKetNumRemove){
if(this.titketNum<10){
System.out.println("售票紧张,停止中");
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.titketNum-=titKetNumRemove;
this.notifyAll();//执行完成后,唤醒所有的线程
}

/**
* 获取剩余票据数
* @return
*/
public int getTiketNumber(){
return titketNum;
}
}
      

        



0 0
原创粉丝点击