诺禾:诺禾通俗易懂的告诉你java多线程中wait和sleep的区别

花10分钟认真的阅读一篇文章,会有意想不到的收获
在学习java多线程的过程中,我们能一定见过sleep和wait这两个方法,这两个方法都是多线程中经常使用的方法,并且它们都可以让当前线程停下来。可是你知道吗?这两个方法其实有很大的差别。
要想弄懂这两个方法的差别,我们可以先简单地看一下多线程的运行状态

  1. New:初始状态,线程被创建,没有调用start()
  2. Runnable:运行状态,Java线程把操作系统中的就绪和运行两种状态统一称为“运行中”
  3. Blocked:阻塞,线程进入等待状态,线程因为某种原因,放弃了CPU的使用权
  4. Waiting:等待状态
  5. timed_waiting:超时等待状态,超时以后自动返回
  6. terminated:终止状态,当前线程执行完毕
    这里介绍多线程的几个状态,主要是想大家看下,在这几个状态的转化中wait和sleep的作用。
    通过上面的图可以看到
    wait使线程从Running到Waitingsleep使线程从Running到timed_waiting:超时等待状态,时间一到自动变回Running状态可以看出wait和sleep都可以使线程中止,但是也存在许多不同,下面就逐一来看下wait和sleep的不同之处
    一、sleep是Thread的方法,wait是Object的方法
    sleep的源码
    可以看到sleep在Thread类中,并且是Thread的一个静态本地方法,所以平时我们调用sleep的时候就Thread.sleep()这样就可以进行调用了。
    wait源码
    可以看到wait方法在Object类中,因为java中所有的类都是继承自object的,所以所有类都可以调用wait方法,这是一个final的方法,同时不是一个静态方法,所以调用该方法需要先实例化一个Object对象才可以
    二、sleep不会去释放锁,但是wait会释放这个锁,并把这个wait的线程加入到这个锁的等待队列中去
    废话少说看例子!
    sleep不会释放锁
    通过输出结果我们可以看到,t1和t2这两个线程是顺序输出的,因为sleep不会释放锁,必须等sleep结束了才会释放锁,下一个线程才能去执行。
    wait会释放锁
    通过这个输出结果可以看到t1和t2这两个线程几乎是同时执行的,这是因为wait在中止线程的时候是直接把线程放到等待队列中的,会直接释放锁
    三、使用wait必须要定义一个synchronized,而sleep不需要
    废话少说,看例子!
    看输出结果可以发现,会报一个非法的监视器错误,这就是因为wait必须要在synchronized修饰的语句块或者方法和类中
    四、使用sleep不需要被唤醒,但是wait是需要notify()或者notifyAll()去唤醒的,除了wait(1000)这种形式
    多线程的状态变化还是比较复杂的,在这其中wait和sleep都能起到使线程中止的目的,但是它俩有很多区别,在实际的使用中要根据具体情况来定。同时“wait和sleep的区别”是很多面试官都喜欢问的,希望看完这篇文章对大家有帮助。

猜你喜欢

转载自blog.51cto.com/14819491/2496600