wait、notify、park、sleep、yield等对比

上图展示了Java中线程各个状态之间的切换,可以看到有非常多的函数可以导致线程状态的变化,具体包括notify、wait、join、yield、park、sleep等。那这些方法有什么区别呢?

  1. 线程让步:yield()

    yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

  2. wait()与yield()对比

    wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而yield()的作用是让步,它也会让当前线程离开“运行状态”。它们的区别是:

    • wait()是让线程由“运行状态”进入到“等待(阻塞)状态”,而不yield()是让线程由“运行状态”进入到“就绪状态”。
    • wait()是会线程释放它所持有对象的同步锁,而yield()方法不会释放锁。
  3. 线程休眠:sleep()

    sleep() 定义在Thread.java中。sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。

  4. sleep()与wait()比较

    wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
    但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。 还有sleep必须指定时间。

  5. sleep()与yield()比较

    sleep和yield的区别在于, sleep可以使优先级低的线程得到执行的机会, 而yield只能使同优先级的线程有执行的机会。

  6. wait()/notify()/notifyAll()

    • wait(),让线程进入等待或超时等待状态,释放所有锁,需要和synchronized搭配使用,没有锁时使用会抛出IllegalMonitorStateException)
    • notify(),也要在synchronized使用,并且应该指定对象。synchronized(),wait(),notify() 对象必须一致,一个synchronized()代码块中只能有1个线程wait()或notify()
    • notifyAll(),是唤醒同一对象下所有等待的线程
  7. LockSupport中的park()和unpark()

    LockSupport比Object的wait/notify有两大优势:

    • LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦。park和wait的主要区别之一就是:wait让线程阻塞前,必须通过synchronized获取同步锁。

    • unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序。

  8. join()

    等待调用join方法的线程结束,

    再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。

  9. interrupt()方法

    • interrupt()是给线程设置中断标志;对于非阻塞中的线程, 只是改变了中断状态, 即Thread.isInterrupted()将返回true; 对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为true。

    • interrupted()是检测中断并清除中断状态;

    • isInterrupted()只检测中断。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2022 Yin Peng
  • 引擎: Hexo   |  主题:修改自 Ayer
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信