一.线程的五种状态
创建,就绪,运行,挂起(包括阻塞,睡眠,等待),结束
1.创建
一个被创建的线程,但是还没有执行线程类的start()方法来启动线程。
2.就绪
调用线程的start()方法后,其实线程进入了就绪状态,切记,并非直接进入运行状态。
3.运行
当处于就绪状态的线程获得时间片后,就进入了运行状态。
4.挂起
挂起是我认为在线程运行状态中最复杂的一个环节,它分为睡眠,等待(又包括超时等待),阻塞三种。要注意这三者的区分。
1)睡眠:sleep()方法是使线程暂停执行一段时间的方法,它是Thread类的静态方法,是线程自身用来控制自身流程的,它会使线程暂停一段时间,在其期间,把执行机会让给其他处于就绪状态的线程,等到睡眠时间一到,此线程会自动“苏醒”。但是需要注意,醒来后进入就绪状态,而不是运行状态。还有需要注意的是虽然它让出cpu的执行权给其他的线程,但是它并不释放锁。
2)等待:等待线程等待的是其他线程执行某些操作,典型的例子就是生产者和消费者的设计模式。wait()方法是基类Object的方法,它又细分为三种wait(),wait(long timeout),wait(long timeout,int nanos),但实际上调用的都是wait(long timeout)方法。wait()方法的主要作用是用于线程间的通信,这个方法会使当前拥有对象锁的进程等待,等到其他线程调用notify()或notifyAll()方法才会醒来,也可以通过参数timeout给他设置一个时间,到时间他会自动醒来,但是需要注意,醒来后进入就绪状态,而不是运行状态。
3)阻塞:阻塞表示线程正在等待对象的锁,试图通过synchronized去获得某个锁,但是这个锁先被其他的线程占有了,那么该线程就处于等待锁释放的状态,即阻塞状态。
5.结束
线程终止运行的状态。
二.注意点
1)阻塞状态的线程可能会直接终止,但等待与睡眠状态的线程只能回到就绪状态。
2)能不用sleep()就不用sleep(),因为它让出cpu却不释放锁,容易造成死锁,比如线程1持有A锁,等待B锁,线程2持有B锁,等待A锁,他们就会处于相互等待的状态。
3)wait()的前提是已经获得锁,在等待其他线程执行某种操作,所以wait()与和它配套的notify(),notifyAll()需要在同步方法或同步代码块中使用,而sleep()可以在任何地方使用。