线程阻塞与等待的区别

  • 简单来说,线程阻塞是被动发生的,当满足线程所需要的条件时线程会自动恢复执行;而线程等待是主动发生的,线程必须等待其他线程的通知才能继续执行。

1. 阻塞(Blocking)

  • 线程阻塞是指线程因为某些原因无法继续执行,进入阻塞状态。常见的阻塞情况包括:

    • I/O 阻塞:执行I/O操作时数据没有准备好。
    • 资源争用阻塞:多个线程获取一个资源而该资源被其他线程占用。
  • 阻塞的线程会被操作系统从可运行队列中移除,直到条件满足再恢复执行。阻塞的线程不会消耗 CPU 资源。

  • 阻塞的特点:

    • 阻塞通常是外部条件决定的,例如I/O操作、等待锁等。
    • 线程进入阻塞后,会被操作系统挂起,直到事件完成或外部条件满足。
    • 阻塞状态下的线程会被挂起,无法继续执行任务,直到外部事件(如 I/O 完成、锁释放等)发生。

2. 等待(Waiting)

  • 等待通常指线程进入一个等待状态,直到其他线程通过某种方式通知它继续执行。线程进入等待状态的常见方式包括:

  • 使用Object.wait()方法:线程调用该方法后进入等待状态,直到被其他线程调用notify()notifyAll()方法唤醒。

  • 使用Thread.join()方法等待另一个线程完成。

  • 使用Condition.await()方法:在使用显示锁(如ReentrantLock)时,可以通过Condation来实现等待和通知机制。

  • 等待的特点:

    • 等待是由线程自身主动触发的。
    • 线程进入等待后,必须等待其他线程的通知才能继续执行。

3. 区别

特性 阻塞(Blocking) 等待(Waiting)
发生的原因 外部条件导致,如I/O操作、资源争用等 线程主动进入等待,直到被通知或条件满足
线程状态 线程会进入阻塞队列,无法继续执行 线程进入等待队列,必须等待其他线程通知
是否主动放弃 CPU线程会被挂起,外部条件满足后恢复执行 线程主动放弃CPU,直到被唤醒或条件满足
典型方法 Thread.sleep()、I/O 操作、锁等待等 Object.wait()Thread.join()Condition.await()
需要通知 不需要其他线程通知 需要其他线程通知,如notify()notifyAll()