zoukankan      html  css  js  c++  java
  • sleep和wait的区别

    参考地址

    1、https://blog.csdn.net/xyh269/article/details/52613507

    2、https://www.cnblogs.com/plmnko/archive/2010/10/15/1851854.html

    1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

    2、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 
       synchronized(x){ 
          x.notify() 
         //或者wait() 
       }

    3、最主要sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

    sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

    4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

    结合synchronized,会更好的理解sleep()和wait()这两个方法,当然也就知道了他们的区别了。这篇博客就一起学习这两个方法

    sleep()

    sleep() 方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。 
    因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。

    下面用一个例子来演示:

    Service类:

    public class Service {
    
        public void mSleep(){
            synchronized(this){
                try{
                    System.out.println(" Sleep 。当前时间:"+System.currentTimeMillis());
                    Thread.sleep(3*1000);
                }
                catch(Exception e){
                    System.out.println(e);
                }
            }
        }
    
        public void mWait(){
            synchronized(this){
                System.out.println(" Wait 。结束时间:"+System.currentTimeMillis());
    
            }
        }
    
    }
    

    就定义了两个方法, mSleep()方法会让调用线程休眠3秒,mWait() 就打印一句话。两个方法都使用了同步锁。

    SleepThread类:

    public class SleepThread implements Runnable{
    
        private Service service;
    
        public SleepThread(Service service){
            this.service = service;
        }
    
        public void run(){
            service.mSleep();
        }
    
    }
    

    线程类,用于调用Service 的mSleep方法

    WaitThread类:

    public class WaitThread implements Runnable{
    
        private Service service;
    
        public WaitThread(Service service){
            this.service = service;
        }
    
        public void run(){
            service.mWait();
        }
    
    }
    

    线程类,用于调用Service 的mWait方法

    测试类:

    public class Test{
        public static void main(String[] args){
    
            Service mService = new Service();
    
            Thread sleepThread = new Thread(new SleepThread(mService));
            Thread waitThread = new Thread(new WaitThread(mService));
            sleepThread.start();
            waitThread.start();
    
        }
    
    }
    

    创建了一个Service对象并赋值给mService,还创建了两个线程并传入mService,也就是说两个线程启动后,调用的是同一个Service对象的方法。 

    先看下结果: 
    这里写图片描述

    梳理一下逻辑:

    首先sleepThread线程会启动起来,然后在run方法里调用Service对象的mSleep方法,到了同步代码块后,this就是Test类里创建的Service对象mService,sleepThread线程获得了Service对象的锁,之后进入了休眠状态,但并没有释放该Service对象的锁。 
    这时waitThread线程也启动了起来,调用Service对象的mWait方法,同样到了同步代码块,因为Service对象的锁已经被sleepThread占了,所以waitThread线程只能干等着。 
    等到sleepThread线程执行完毕(休眠结束)后释放了同步锁,waitThread线程拿到了同步锁,会继续执行,mWait才会被调用。

    如果sleepThread释放了机锁的话,waitThread 的任务会马上得到执行。从打印结果可以看出,waitThread 的任务是3秒钟之后才得到执行。

    同步锁,锁住的是一个对象。如果一个线程拿到了一个对象的机锁去执行一段同步代码块了,那么其他线程都不能执行这个对象的其他同步代码块。 
    在这个例子中就是sleepThread线程拿到了service对象的同步锁,进入后休眠,但没有释放机锁,那么waitThread线程是不能执行这个service对象的其他同步代码块的,也就就是不能进入这一段代码

    synchronized(this){
                System.out.println(" Wait 。结束时间:"+System.currentTimeMillis());
    
    }

    相信现在你已经理解了sleep方法没有释放机锁会带来什么结果了,那么继续wait

    wait()

    wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程

    下面修改程序如下所示:

    public class Service {
    
        public void mSleep(){
            synchronized(this){
    
                try{
                    Thread.sleep(3*1000);
                    this.notifyAll();
                    System.out.println(" 唤醒等待 。 结束时间:"+System.currentTimeMillis());
                }
                catch(Exception e){
                    System.out.println(e);
                }
    
            }
    
        }
    
        public void mWait(){
    
            synchronized(this){
                try{
                    System.out.println(" 等待开始 。 当前时间:"+System.currentTimeMillis());
                    this.wait();
                }catch(Exception e){
                    System.out.println(e);
                }
            }
    
        }
    
    }

    测试类:

    public class Test{
    
        public static void main(String[] args){
    
            Service mService = new Service();
    
            Thread sleepThread = new Thread(new SleepThread(mService));
            Thread waitThread = new Thread(new WaitThread(mService));
            waitThread.start();
            sleepThread.start();
    
        }
    
    }

    同样先看下打印结果 
    这里写图片描述

    这里是先让 waitThread线程启动起来,然后waitThread线程进入等待状态,并释放了Service对象的锁,这时sleepThread也启动了,来到了mSleep方法的同步代码块,因为之前的waitThread线程已经释放了Service对象的机锁,sleepThread可以拿到对象锁,所以mSleep方法是会被马上调用的。然后sleepThread线程就是进入了睡眠状态,等到3秒休眠结束后调用notifyAll()唤醒了waitThread线程。

    综上所诉: 
    sleep() 和 wait() 的区别就是 调用sleep方法的线程不会释放对象锁,而调用wait() 方法会释放对象锁

  • 相关阅读:
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale
    CodeForces 785B Anton and Classes
    CodeForces 785A Anton and Polyhedrons
    爱奇艺全国高校算法大赛初赛C
    爱奇艺全国高校算法大赛初赛B
    爱奇艺全国高校算法大赛初赛A
    EOJ 3265 七巧板
    EOJ 3256 拼音魔法
    EOJ 3262 黑心啤酒厂
  • 原文地址:https://www.cnblogs.com/suntp/p/9513423.html
Copyright © 2011-2022 走看看