notify()是与wait()相对应的如果一个线程调用wait()永远不被唤醒则线程永远处于等候状态,但是线程被唤醒不等于说线程就开始运行,首先必须根据优先级排队等待,当然如果你的被唤醒的线程的优先级相当高则可能被唤醒后立刻运行,或者队列中没有其他的线程,你的被唤醒的线程也可能立刻运行。线程有几个状态,也叫线程的生存周期,搞清楚就好了。

解决方案 »

  1.   

    不一定
    先给你解释一下,每个对象都有一个锁计数器,他保存着当前锁的owner有几个synchronized方法被调用。锁的owner每调用一个新的synchronized方法,计数器++,每次synchronized方法退出时,计数器--;计数器为0时,解锁。
    这样,如果一个线程调用了synchronized方法而得锁,计数器为1,这个方法因为某些条件不满足,不能继续,用wait挂起自己,然后,其他线程有机会调用了另一个synchronized方法来满足这个条件,并且在退出前调用了notify或者notifyAll来通知刚才那个被挂起的线程,使之能继续运行。这是一般情况,但是如果这种情况,刚才那个线程在synchronized方法A中没有wait来挂起自己,而是调用了他拥有的对象的另一个方法B,满足了条件,注意,这时他拥有的对象的锁计数器为2,她调用notify,这个synchronized方法B退出之后,锁计数器变为1,所以,这个线程还有钥匙,仍然不放弃此对象,只当A也退出时,锁计数器才变为0,这个线程才松手,下面是我写的两个例子,来说明这个问题,例子一:假设Daniel是个很有钱的人,总往垃圾箱里扔东西,而Kate和Jack很穷,总去垃圾箱捡Daniel扔的东西,直到30为止,可能是垃圾箱被城管挪走了,程序结束。这是正常情况。
    public class WaitNotifyTest
    {
    public static void main(String[] args) 
    {
    Dustbin db = new Dustbin();
    PeopleThread people1 = new PeopleThread(db, "Daniel");
    PeopleThread people2 = new PeopleThread(db, "Jack");
    PeopleThread people3 = new PeopleThread(db, "Kate");
    people1.start();
    people2.start();
    people3.start();
    }
    }class Dustbin
    {
    private int tonnage = 0;
    private int operation = 0;
    public boolean end()
    {
    return operation>30;
    }
    public synchronized void get(String operator)
    {
    int op = operation++;
    System.out.println(operator + " Operation " + op + " is a get call, current tonnage is " + tonnage);
    try
    {
    while(tonnage<10){
    System.out.println(operator + " Operation " + op + " blocked, waiting for others");
    wait();
    }
    System.out.println(operator + " Operation " + op + " resumed");
    tonnage-=10;
    notifyAll();
    System.out.println(operator + " Operation " + op + " notified others, current tonnage is " + tonnage);
    }
    catch (Exception e)
    {System.out.println(e);}
    }
    public synchronized void put(String operator)
    {
    int op = operation++;
    System.out.println(operator + " Operation " + op + " is a put call, current tonnage is " + tonnage);
    tonnage += 10;
    notifyAll();
    System.out.println(operator + " Operation " + op + " notified others, current tonnage is " + tonnage);
    }
    };class PeopleThread extends Thread
    {
    private Dustbin dustbin = null;
    private String name = null;
    PeopleThread(Dustbin db, String name)
    {
    dustbin = db;
    this.name = name;
    }
    public void run()
    {
    try
    {
    while(!dustbin.end()){
    if(name.equals("Daniel"))
    dustbin.put(name);
    else
    dustbin.get(name);
    }
    }
    catch (Exception e)
    {System.out.println(e);} } 
    };
    运行结果很有意思,Kate和Jack抢着捡Daniel的破烂,每次Daniel往垃圾桶人一个东西(PUT),Kate和Jack总是只有一个人能抢到(GET),然后告诉别人,行了,这次我抢到了,我赢了,然后如果桶里没了,大家接着再等。
    另外一种情况就是你的问题了,假设Daniel性格迥异,生活总是大富大贫的波荡起伏,一会把电视机和冰箱扔到垃圾箱,下个月由穷了,又去垃圾箱找东西,再捡回来。有时候垃圾箱是空的,Daniel正么办呢?还好,Daniel笃信上帝,每次弹尽粮绝的时候,上帝就往他家的垃圾桶里扔点东西,Daniel就又捡到了,上帝扔东西的时候,垃圾箱的锁计数器为2,代码如下
    public class WaitNotifyTest2
    {
    public static void main(String[] args) 
    {
    Dustbin db = new Dustbin();
    PeopleThread people1 = new PeopleThread(db, "Daniel");
    people1.start();
    }
    }class Dustbin
    {
    private int tonnage = 0;
    private int operation = 0;
    public boolean end()
    {
    return operation>30;
    }
    public synchronized void get(String operator)
    {
    int op = operation++;
    System.out.println(operator + " Operation " + op + " is a GET call, current tonnage is " + tonnage);
    try
    {
    while(tonnage<10){
    System.out.println(operator + " Operation " + op + " blocked, waiting for others");
    put("God");//in this put, lock count is 2
    //wait(); do not wait
    }
    System.out.println(operator + " Operation " + op + " resumed");
    tonnage-=10;
    notifyAll();
    System.out.println(operator + " Operation " + op + " notified others, current tonnage is " + tonnage);
    }
    catch (Exception e)
    {System.out.println(e);}
    }
    public synchronized void put(String operator)
    {
    int op = operation++;
    System.out.println(operator + " Operation " + op + " is a PUT call, current tonnage is " + tonnage);
    tonnage += 10;
    notifyAll();
    System.out.println(operator + " Operation " + op + " notified others, current tonnage is " + tonnage);
    }
    };class PeopleThread extends Thread
    {
    private Dustbin dustbin = null;
    private String name = null;
    PeopleThread(Dustbin db, String name)
    {
    dustbin = db;
    this.name = name;
    }
    public void run()
    {
    try
    {
    while(!dustbin.end()){
    if(Math.random()>0.5)
    dustbin.put(name);
    else
    dustbin.get(name);
    }
    }
    catch (Exception e)
    {System.out.println(e);} } 
    };
    本人拙见, 如有错误欢迎指出,另外代码命名很不规则,随手敲得,不好意思了