• 多线程中sleep和wait的区别


    前几天去UC笔试,有一道简答题问到了。之前还真一直没留意到这个问题,所以答得也不好。

    无论学习什么都好,通过对比学习更有利于发现事物的共性和个性,对于知识点的理解更有明显效果(这也可能是UC笔试题上,5道简答题中,有4道都是关于X与Y的区别的问题的原因之一)。

    既然自己答得不好,那就写下这篇随笔,来警示下自己(不仅是sleep与wait区别,还有多用这种对比学习的学习方式)。

    翻了很多资料,说的最多的一句就是,

      sleep与wait最主要的区别在于,sleep与wait都可以使线程等待,但sleep不会释放资源而wait会释放资源。

    还有就是,wait方法只能在同步块或者同步方法中执行。

      怎么理解这句话?

      这里有个例子:我登录图书管理系统订了一本 《疯狂JAVA讲义》,当我去到图书管排队借书,到了借书窗口的时候,我告诉管理员我们的名字和预定的书,然后管理员查询到我预订的信息,然后安排助理去预定的图书中找这本书,这个时候,如果我用的是sleep模式,我就一直站在窗口前,直到管理员给我这本书。如果我用的是wait模式,那么我就让出位置给在排队的后面的同学,到旁边的椅子上等待,直到通知我,我要的书找到了,我再回到队伍中排队取票。

      这样是不是明白对了?

    下面来验证一下,sleep是否不会释放资源而wait会释放资源。

    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException {
            
            new Thread(new Thread1()).start();
            
            synchronized (ThreadTest.class) {
                System.out.println("Main Thread go to sleep  : currenttime-->"+System.currentTimeMillis());
                //sleep过程不会释放资源
                Thread.sleep(10000);
            }
            System.out.println("Main Thread get up : currenttime-->"+System.currentTimeMillis());
                new Thread(new Thread2()).start();
                System.out.println("Main Thread over");
        }
        static class Thread1 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread1 is ready :currenttime-->"+System.currentTimeMillis());
                //因为sleep不会释放资源,所以在主线程sleep结束前,是不能取得资源的锁,而是在等待
                synchronized (ThreadTest.class) {
                System.out.println("Thread1 is running :currenttime-->"+System.currentTimeMillis());
                    System.out.println("Thread1 wait :currenttime-->"+System.currentTimeMillis());
                    try {
                        ThreadTest.class.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }              
                System.out.println("Thread1 is over ");
            }
            }
            
        }
        static class Thread2 implements Runnable{
            @Override
            public void run() {
            System.out.println("Thread2 is ready :currenttime-->"+System.currentTimeMillis());
    synchronized (ThreadTest.class){ System.out.println("Thread2 is running :currenttime-->"+System.currentTimeMillis()); System.out.println("Thread2 notify :currenttime-->"+System.currentTimeMillis()); ThreadTest.class.notify(); System.out.println("Thread2 is over"); } } } }

    输出结果:

    Main Thread go to sleep  : currenttime-->1400232812969
    Thread1 is ready :currenttime-->1400232812969
    Main Thread get up : currenttime-->1400232822970
    Thread1 is running :currenttime-->1400232822970
    Thread1 wait :currenttime-->1400232822970
    Main Thread over
    Thread2 is ready :currenttime-->1400232822972
    Thread2 is running :currenttime-->1400232822972
    Thread2 notify :currenttime-->1400232822972
    Thread2 is over
    Thread1 is over

      由结果可以看出,当主线程sleep10s中的过程,Thread1仅仅处于ready状态,而一直没有获取到ThreadTest.class的锁,原因在于,主线程在sleep的之前已经获取了该资源的锁,这也验证了在用sleep()的时候不会释放资源。
       当主线程sleep完之后,Thread1获取到了ThreadTest.class的锁,然后调用了wait方法(wait方法是Object的静态方法)。在调用该方法后,Thread2启动,且顺利获取到ThreadTest.class的锁,这也验证了在用wait()方法的时候会释放资源。

      最后,在Thread2中调用notify方法(notify方法也是Object的静态方法,作用是唤醒在同步监视器上等待的一个线程),然后我们看到 "Thread1 is over"。wait 方法与 notify 方法或notifyAll方法 搭配使用,来协调线程运行。如果我们把Thread2中的notify方法去掉,会发现最后Thread1并没有再次运行,也就不会打印"Thread1 is over"。

  • 相关阅读:
    jpype
    Java获取类中的所有方法
    SQL中INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN区别
    如何用命令将本地项目上传到git
    Java连接Mysql:通过配置文件
    lsof -i:port_number
    yum install lsof
    Git的基本使用方法(受益匪浅)
    [后端]gitlab之gitlab-ci自动部署
    centos7安装redis-4.0.1集群
  • 原文地址:https://www.cnblogs.com/hellocsl/p/3732733.html
Copyright © 2020-2023  润新知