sleep(),wait(),join(),yield(),noitfy(),notifyAll() TODO

269 阅读4分钟

thread.yield(); 

  • Thread对象的native方法。 
  • 让出cpu,避免独占cpu太长时间,让其他线程有被执行的机会。
  •  让出cpu后该线程可以立即参与到cpu的抢占之中。 
  • 方法生效后该线程会进入就绪状态。 告诉调度器该线程愿意让出CPU的使用权,以免某个线程过度占用CPU。从而使CPU充分被协调利用。
  • 生产环境很少使用 (调度器可以选择忽略这个提示)

一句话总结:让出cpu,可立即参与cpu抢占,线程JAVA线程的RUNNABLE状态,对应****进入操作系统的就绪状态。

应用场景:

object.wait()

  • Object对象的native方法。

  • 让出锁和cpu,避免独占锁太长时间,让其他线程有获得锁的机会。---哪个线程调用该方法,哪个线程就wait

  • 方法生效后调用线程进入阻塞状态,线程会一直等待直到:

  • 持有相同锁的线程调用该对象的notify()或者notifyAll(); 

  • 达到指定的等待时间。等待时间为0则只能等待其他线程唤醒 

  • 调用wait()的线程必须持有当前对象的锁,如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。 因此wait()和notify()必须在synchronized函数或synchronized块中进行调用(不能是api实现的锁吗?不行吧,因为实现机制不一样)

  • 被唤醒后可以与其他线程平等地参与锁的竞争,没有抢占锁的优先级

  • wait() --> 进入等待池,不能参与锁竞争,notify() --> 从等待池到锁池,可以参与锁竞争

一句话总结:让出cpu和锁,直到被唤醒后可以参与锁的竞争,进而参与cpu竞争。

wait() --> 进入JAVA线程的WAITING状态,对应操作系统的阻塞状态

wait(long time)--> JAVA线程的TIME_WAITING状态,对应操作系统的阻塞状态

object.notify()

  • Object对象的native方法。
  • 与wait()搭配使用,唤醒任意一个正在等待该对象锁的线程 
  • 需在synchronized方法或方法块中调用(需要先持有锁才能调用锁呀)

一句话总结:唤醒等待该对象锁的任意一个线程,需要在同步块或同步方法中调用。

**wait指定时间或者被notify唤醒后线程进入JAVA的BLOCKED状态,对应操作系统的阻塞状态(因为还未获得锁,还在阻塞),获得锁后,进入就绪状态,对应JAVA的RUNNABLE状态
**

object.notifyAll()

  • Object对象的native方法
  • 与notify()类似,只不过是唤醒所有正在等待该对象锁的线程

一句话总结:唤醒等待该对象锁的所有线程,需要在同步块或同步方法中调用。

wait()和notify()应用场景:线程间通信

thread.sleep(long time)

  • Thread类的静态本地方法。
  • 暂停执行一段时间(time),期间会让出cpu,但不释放持有的锁(若有)。
  • 方法生效后该线程进入阻塞状态

一句话总结:让出cpu,但不让出锁,sleep期间不能参与cpu竞争,sleep后线程进入JAVA中的TIME_WAITING状态,对应操作系统的阻塞状态。

应用场景:

thread.join()

  • Thread对象方法。synchronized。
  • 当前线程必须等被join的子线程执行完毕后才能执行
  • thread.join(long millis):当前线程如果等待millis时间后,被join线程还未执行完成, 则当前线程将自动进入就绪状态,重新等待cpu调度 
  • thread.join();当前线程将一直等待,直到被join线程执行完毕 
  • 在join期间,当前线程(父线程)会让出对象锁和cpu
  • 原理:底层使用wait方法。父线程调用子线程.join()==> 当前线程被wait(),直到子线程执行结束,被唤醒。

  • 为什么要在while(isAlive())循环中wait()?

  • 因为父线程要wait到被join线程结束,而不是wait一次notify,就算中途被notify了但是被join线程还未结束,也是不行。(注释中说的是虚假唤醒)

  • 父线程是如何唤醒的?

  • 关键在线程的exit()方法,线程执行结束时会去做一些清理工作,此时会唤醒所有等待该锁的对象。

一句话总结:当前线程让出cpu和对象锁,进入阻塞状态,等待被join线程执行完后被join线程唤醒,可参与锁竞争,状态变化同wait()

**应用场景:线程间通信
**

补充

TODO

各自的使用场景

interrupt()

stop()

suspend()

stop()

juejin.cn/post/684490…

线程中断,如何停止一个线程

  • 出场率比较高的一道多线程安全面试题

  • Java多线程神器:join使用及原理

  • 面试常考:Synchronized 有几种用法?

  • 任务并行神器:Fork & Join 框架详解