Moosphan/Android-Daily-Interview

2019-08-08:谈一谈线程sleep()和wait()的区别?

MoJieBlog opened this issue · 14 comments

截止今天,关于线程的面试题我能想到的问题基本上都问了。大家看有没有什么我没想到的问题,可以去问题征集区填写下。或者直接群里发出来也行。

wait:资源不持有,object方法
sleep:资源持有,线程方法

wait: 释放锁
sleep: 没有释放锁

sleep 是Thread类的方法,wait是Object类的方法
sleep不释放锁,wait释放锁
sleep不需要Synchronized ,wait需要Synchronized
sleep不需要唤醒,wait需要唤醒(除wait(int time))

wait()的线程状态能够被notify,notufyall唤醒,而sleep()的线程状态不能被唤醒。
wait()进入等待期会释放锁,sleep()不会释放锁
wait只能在同步(synchronize)环境中被调用,而sleep不需要

sleep()和wait() CPU时间片都会释放
notify() 只唤醒一个等待(对象的)线程并使该线程开始执行
notifyAll() 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现

wait()的线程状态能够被notify,notufyall唤醒,而sleep()的线程状态不能被唤醒。
wait()进入等待期会释放锁,sleep()不会释放锁
wait只能在同步(synchronize)环境中被调用,而sleep不需要

sleep 也是可以被唤醒的,通过interupt方法,但是会抛出一个打断异常,只要捕获它,程序依然能够继续执行。
https://www.cnblogs.com/thinfog/p/11250913.html
这是我对于线程状态的研究,如有错误,请大家指教。

sleep是Thread里面的方法,wait是Object里面的方法
sleep不释放锁,wait释放锁
sleep不能被唤醒,wait可以被唤醒
sleep不需要synchronize,wait需要

sleep 是Thread的 wait是Object的
sleep 不释放锁 wait释放锁(wait需要notify或者notifyall来唤醒,只能在synchronize里面用)

我想提另外一个问题, thread.yield 和 thread.join

public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

wait是Object中的方法,sleep是Thread中的方法
wait会释放锁,sleep不释放锁
wait只能在synchronize中使用,需要notify或者notifyall来唤醒;sleep不需要被唤醒
sleep也可以被唤醒,使用interupt方法,但是需要捕获异常

1.sleep是Thread的静态方法,所以通过对象名.sleep()调用并不会使得该对象线程进入休眠,而是当前线程进入休眠,wait()是Object类中的方法,因为锁对象是任意的,而Object类是所有类的基类。
2.sleep()调用之后不释放锁,wait()方法调用之后释放锁。
3.sleep()方法必须要传入参数,而wait()方法可以传入也可以不传入参数,参数即为时间。
4.sleep()方法可以用在任何地方,wait()方法只能用在同步方法或者同步代码块中。因为wait(),notify(),notifyAll()都是对锁对象所在的线程进行操作,必须先要有锁对象。
5.sleep()方法不需要唤醒,在一定时间后(即参数),该线程会自动醒来,wait()必须由notify()或者notifyAll()来唤醒

我想问一个问题,wait() 之后一定要 notify 之后才能唤醒嘛 ?

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("run start ");
                synchronized (mObject) {
                    try {
                        mObject.wait(2000);
                        System.out.println("run continue ");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("run stop ");
            }
        }).start();
    }

运行结果是这样的,这里并没有 notify ,wait 之后的代码也运行了,这是为什么 ?

run start 
run continue 
run stop 

image
你这里,是等待2秒,并不是永远等待