Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 426|回复: 0

[Java线程学习]wait与notify,sleep与join及线程同步问题

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-28 23:56:44 | 显示全部楼层 |阅读模式
    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 !");
         }
    } 上面的代码很简短,而且表明了执行顺序,运行结果: C:java>java Syn
    People 1 is brushing !
    People 1 has burshed !
    People 2 is brushing !
    People 2 has burshed !
    People 1 is releasing !
    People 1 has released !
    People 2 is releasing !
    People 2 has released ! 前面只说明了wait和notify这两个方法,这里讨论一下sleep和join,说实在的这两个方法比wait和notify简单的多.

    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 !");
             }
    }
    运行结果: C:java>java Syn
    A is bathing !
    B has waited 10 minutes
    A has bathed !
    B has waited 20 minutes
    B can bath now!
      这里连同步都不需要,不过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 !");
             }
    }
    运行结果: C:java>java Syn
    A is bathing !
    A has bathed !
    B can bath now! 这样只要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 !");
             }
    } 运行结果: C:java>java Syn
    A is bathing !
    A has bathed !
    B can bath now! 对于一般的对象就要用wait和notify了,但是对于一个线程来说,join方法有时候更加方便。     
      


    源码下载:http://file.javaxxz.com/2014/10/28/235644562.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 01:51 , Processed in 0.353607 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表