其实只要记blockied阻塞态和waiting等待态这两个状态即可
blocking状态和waiting状态的区别:
线程竞争锁,没有获取到锁就会进入到blocking阻塞态,获取到锁就会从blocking阻塞态变成running运行态
正在运行的线程1需要等待另一个线程2运行的结果,此时线程1就会主动调用wait()方法,进入waiting等待状态,当其他线程,调用notify方法的时候,就会唤醒处于waiting态的线程,线程被唤醒后并不一定会立即获得锁,而是进入blocked阻塞态,和其他处于blocked阻塞态的线程一起竞争锁,
其他图都不要管,就记下面这张图就行:
1.new状态 新建状态 调用new Thread()线程就进入这个状态了
2.Runnable 运行状态 线程调用start方法后,该线程就会进入运行状态
3.Blocked状态 阻塞状态,没有抢到同步锁就会变成阻塞状态
4.waiting 等待状态 ,占有锁(假设锁是obj对象)的线程调用obj.wait()方法,就会把锁让出去,自己进入这把锁的等待队列里面,只有等占有锁的调用obj.notify()方法,才会去这把锁的等待队列中选一个线程让他占有锁进入runnable运行状态。
Thread t1 = new Thread( () ->
{
synchronized (obj)
{
}
});
Thread t2 = new Thread( () ->
{
synchronized (obj)
{
}
});
Thread t3 = new Thread( () ->
{
synchronized (obj)
{
}
});
5.time-waiting状态:把锁让出去,指定时间结束,就把锁回收
6.terminated 终止状态 线程的run()方法中的指令执行完成后的状态。
blocked状态和wait状态的区别:
blocked状态是多个线程在竞争Synchronized锁的时候,没有竞争到的就进入blocked状态,也就是说不需要调用什么方法让线程从Runnable状态变成blocked状态,也不需要调用什么方法从blocked状态变成Runnable方法
而wait状态需要持有锁的线程调用obj.wait()方法才会进入wait状态,占有锁的线程调用obj.notify()方法,才会去这把锁的等待队列中选一个线程让他占有锁进入runnable运行状态
总结:(1)blocked状态是锁竞争失败后,被动触发的状态,而waiting是人为主动触发的状态
(2)而处于blocked状态的唤醒,是锁释放出来后自动触发的
waiting状态的唤醒,是必须通过特定方法来主动唤醒的
sleep方法和wait方法的区别:
两者都会让线程进入休眠状态,区别在于
(1)使用方法不一样:wait属于Object类的方法,sleep属于Thread类的方法
(2)thread.sleep()方法不会释放对象锁,如果线程本身持有锁,那虽然休眠还是持有锁,而obj.wai()t方法会释放对象锁
(3)thread.sleep()可以不需要搭配synchronized使用,而obj.wait()必须搭配synchronized使用
看到这里就可以了
Runnable状态调用sleep方法,比如sleep(1000),就会进入timed-waiting有时间的等待状态
如果别的线程B在一个线程A中调用了join方法,就会使得线程A进入永远等待waiting状态
最后如果Runnable状态的线程想要获得锁,但是没有获取到,就会进入到阻塞态blocked
创建(初始),就绪,运行,阻塞,死亡
虽然在上面的图里面是有五种状态,但是在java代码里面其实是有六个状态的:
和上面的图区别在于:
(1)将就绪态Ready和运行态Running合二为一,只剩一个运行状态Runnable
这是因为一个线程一次在cpu上运行很短的时间(比如10~20ms,此时线程处于running状态),然后就要被切换下来放到调度队列的队尾(此时线程处于ready状态),由于线程在这两种状态之间切换的很快,所以区分这两种状态没什么意义
(2)除了有阻塞态,新加了新的状态:等待状态
阻塞状态,该线程等待的是其他线程释放锁
等待状态,该线程等待的是其他线程通知或者中断
(等待状态是没有等到结果就一直等待,超时等待是超过指定时间没有等到结果就返回到Runnable状态)
注意:通过thread.getState()方法可以获取线程状态