大鱼

wait,notify,sleep,join这几个方法很常用


wait,notify,sleep,join这几个方法很常用,这里涉及到多线程和同步问题,这里稍微解释一下.

1.wait和notify
这两个方法都是Object中的方法,放在一块是因为他们关系非常密切.
wait就是等待这个对象的同步锁,不过调用这个方法必须先获得这个对象的同步锁,就这一点很多人就搞晕了.
这里先解释一下这两个方法,然后给出一个小例子说明.

wait:等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则后收到一个IllegalMonitorStateException,这个是运行时异常.调用这个方法后,就放弃了这个同步锁了.如果不带参数的wait方法就只有等别人唤醒了,如果带一个参数的
化就设置等待最长时间,过了这个时间即使没有人唤醒这个线程也不再等待了.

notify:唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),但是notifyAll可以唤醒所有等待的线程,注意唤醒的时在notify之前wait的线程,之后的没有效果.

这里举一个通俗的例子,两个人共有一个卫生间(每次只能一个人用),他们都要刷牙和方便,他们是这样约定的,轮流用,第一个人先刷牙,然后第二个人刷牙...

 

class Syn
{
        public static void main(String[] args) throws Exception
        {
            TwoPeople.ONE.start();
            TwoPeople.TWO.start();
        }
}


class TwoPeople extends Thread
{
    private int i=0;
    static Thread ONE=new TwoPeople(1);
    static Thread TWO=new TwoPeople(2);

    static Object washroom=new Object();   
    private TwoPeople(int i){this.i=i;}
    public void run(){
        synchronized(washroom){
            try{
                if(i==1){
                    brush(); //1
                  washroom.wait(); //2
                    release(); //6  
                    washroom.notify(); //7
                }
            else{
                    brush(); //3
                    washroom.notify(); //4
                    washroom.wait(); //5
                    release(); //8
            }
            }catch(InterruptedException e){e.printStackTrace();}
        }
    }
    private void brush() {
            System.out.println("People "+i+" is brushing !");
             try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
            //延迟两秒看效果
            System.out.println("People "+i+" has burshed !");
    }
    private void release(){
            System.out.println("People "+i+" is releasing !");
            try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
            //延迟两秒看效果
            System.out.println("People "+i+" has released !");
    }
};

上面的代码很简短,而且表明了执行顺序,至于join和sleep还是下次再讨论吧.

 

 

 


wait,notify,sleep,join和线程同步问题(续)
昨天没有时间写完这篇,今天补上,前面只说明了wait和notify这两个方法,这里讨论一下sleep和join,说实在的这两个方法比wait和notify简单的多.
http://blog.csdn.net/treeroot/archive/2004/11/10/175508.aspx

sleep:Thread的静态方法,当前线程休眠一段时间,时间到了再恢复可运行状态,时间到了不一定就执行吧,还得竞争CPU呢.

join:这个方法其实就是特殊的wait,wait方法一般都需要别人notify(当然也可以设置超时),但是join方法就不需要别人notify了,一直等到这个线程死亡(就相当于这个线程临时前告诉那些在等它的人:你们进来吧!)

本人不是很会举例子,还是两个人公用一个卫生间吧,这回不刷牙了,改洗澡吧,总不能两个人同时洗澡吧!就算可以,这里假设不可以吧.情况时这样的:A在洗澡,B要等。

第一种情况:
B很聪明的,A洗澡可能要20分钟到1小时,我就先睡10分钟看看好了没有,没有好就再睡10分钟,最多多等10分钟而已吧.


class Syn
{
        public static void main(String[] args) throws Exception
       {
               Thread a=new Bathing();
                a.start();
                //B
                int time=0;
                while(a.isAlive()){
                        Thread.sleep(10000);
                        time+=10;
                        System.out.println("B has waited "+time+" minutes");
                }
                System.out.println("B can bath now!");
        }
}

class Bathing extends Thread
{
        public void run(){
                bathing();
        }
        private void bathing() {
                System.out.println("A is bathing !");
                try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}
                //延迟20秒看效果
                System.out.println("A has bathed !");
        }
};


这里连同步都不需要,不过B可能需要多等一段时间,因为它可能刚好去敲门A还没有洗完,于是他又去睡,结果刚睡下A就洗完了.
第二种情况:
B变得更加聪明了,这样等我不是亏了,如果我10分钟敲一次门,我可能要多等10分钟,但是如果我每秒敲一次我也没法睡呀,于是想了一个高招,装了一个机关,当A出来的时候机关就会按响门铃,这样B就可以高枕无忧了。

class Syn
{
        public static void main(String[] args) throws Exception
        {
                Thread a=new Bathing();
                a.start();
                //B
                int time=0;
                a.join();
                System.out.println("B can bath now!");
          }
}

class Bathing extends Thread
{
        public void run(){
                bathing();
        }
        private void bathing() {
                System.out.println("A is bathing !");
                try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}
                //延迟20秒看效果
                System.out.println("A has bathed !");
        }
};

这样只要A一洗完,B就会被唤醒,这里A并没有去notify他,但是还是间接的通知了B,当然这里也可以用wati和notify实现,不过就显得不好了。

class Syn
{
        public static void main(String[] args) throws Exception
        {
                Thread a=new Bathing();
                a.start();
                //B
                int time=0;
                synchronized(a){a.wait();}
                System.out.println("B can bath now!");
        }
}

class Bathing extends Thread
{
        public void run(){
                synchronized(this){
                    bathing();
                    notify();
                }
        }
        private void bathing() {
                System.out.println("A is bathing !");
                try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}
                //延迟20秒看效果
                System.out.println("A has bathed !");
        }
};

对于一般的对象就要用wait和notify了,但是对于一个线程来说,join方法有时候更加方便。

 

posted on 2009-03-15 21:49 大鱼 阅读(230) 评论(0)  编辑  收藏 所属分类: j2se


只有注册用户登录后才能发表评论。


网站导航: