线程状态,BLOCKED和WAITING有什么区别?

线程状态,BLOCKED和WAITING有什么区别?

对Java中线程状态的认识。

转载自:https://www.zhihu.com/question/27654579/answer/252912242

 

一、Java中的线程状态

先来一张线程状态转化图:

v2-6fdc939e35ec801c31ea515e80a88367_hd

想要记住Java中的线程状态,只要理解并且牢记这张图就可以了。

在Java中线程的状态一共被分成6种:

(1)初始态:NEW

创建一个Thread对象,但还未调用start()启动线程时,线程处于初始态。

(2)运行态:RUNNABLE

在Java中,运行态包括就绪态和运行态。

  1. 就绪态:该状态下的线程已经获得执行所需的所有资源,只要CPU分配执行权就能运行。所有就绪态的线程存放在就绪队列中。
  2. 运行态:获得CPU执行权,正在执行的线程。由于一个CPU同一时刻只能执行一条线程,因此每个CPU每个时刻只有一条运行态的线程。

(3)阻塞态

  1. 当一条正在执行的线程请求某一资源失败时,就会进入阻塞态。
  2. 在Java中,阻塞态专指请求锁失败时进入的状态。
  3. 由一个阻塞队列存放所有阻塞态的线程。
  4. 处于阻塞态的线程会不断请求资源,一旦请求成功,就会进入就绪队列,等待执行。

PS:锁、IO、Socket等都资源。

(4)等待态

  1. 当前线程中调用wait(不带参)、join、park函数时,当前线程就会进入等待态。
  2. 也有一个等待队列存放所有等待态的线程。
  3. 线程处于等待态表示它需要(只能)等待其他线程的指示才能继续运行。
  4. 进入等待态的线程会释放CPU执行权,并释放资源(比如锁)

(5)超时等待态

  1. 当运行中的线程调用sleep(time)、wait(带参)、join、parkNanos、parkUntil时,就会进入该状态。
  2. 它和等待态一样,并不是因为请求不到资源,而是主动进入,并且进入后需要其他线程唤醒。
  3. 进入该状态后释放CPU执行权和占有的资源(sleep比较特殊,不会释放锁资源)。
  4. 与等待态的区别:到了超时时间后自动进入阻塞队列,开始竞争锁(sleep不会释放锁资源,所以会直接进入就绪状态,等待CPU资源)。

(6)终止态

线程执行结束后的状态。

(7)注意

  1. wait()方法会释放CPU执行权和占有的锁。
  2. sleep(long)方法仅释放CPU使用权,锁仍然占用。线程被放入超时等待队列,与yield相比,它(可能)会使线程较长时间得不到运行。
  3. yield()方法仅释放CPU执行权,锁仍然占用,线程会被放入就绪队列,会在短时间内再次执行。
  4. wait和notify必须配套使用,即必须使用同一把锁调用。
  5. wait和notify必须放在一个同步块中。
  6. 调用wait和notify的对象必须是他们所处同步块的锁对象。

(8)个人疑问

1.为什么说“sleep(long)后线程被放入超时等待队列,与yield相比,它(可能)会使线程较长时间得不到运行”呢?

个人认为:

线程执行到sleep(long)时,会主动释放CPU执行权,但是依然占用锁。线程会被放入超时等待队列,等待long这段时间。当睡眠时间到达(sleep interval expires)或者被打扰(interrupted)后,线程才会被放入就绪队列(进入就绪状态),等待CPU资源。

线程执行到yield()时,同样会主动释放CPU执行权,但是依然占用锁。不同的是,线程会被直接放入就绪队列,等待CPU资源。所以更可能提早执行。

2.等待态如何进入阻塞态?

如果线程调用了一个wait()方法,那么这个线程是进入等待态还是进入阻塞态?

个人认为:

要看这条线程需不需要获得锁。如果带锁的线程A调用了wait()方法,就会让出CPU资源并且释放锁。就算这条线程A被别的线程notify了,还是需要获得锁才能执行,就会进入阻塞态。

如果线程A不需要获得锁,调用wait()方法之后,依然会让出CPU资源。因为不需要获得锁就能继续执行,线程A被别的线程notify后,就会直接进入就绪态,等待CPU资源。

二、问题的回答

看完上面的解读后,尝试回答问题:

BLOCKED和WAITING都是非活动线程的状态。WAITING状态中的线程是已经拿到了CPU时间,但是需要等待某种事件发生(比如别的线程的执行阶段),所以主动释放了CPU资源,直到某些事件调用了notify()唤醒(可能进入就绪态,也可能进入阻塞态)。

也就是说,WAITTING状态中的线程是自己不想要CPU时间。

但是BLOCKED状态中的线程是想要获得CPU时间的,遗憾的是,BLOCKED线程没有获得锁,所以连进入就绪态的机会都没有。如果BLOCKED线程竞争到了锁,才会进入就绪态,等待CPU资源。

三、总结

直接搬运别人的系统总结,希望能记住并且理解。

发布者

xie4ever

发表评论

电子邮件地址不会被公开。