对于线程来说,它既不是一启动就进入执行状态,也不是一直处于执行状态.它的生命周期总体为:
- 新建(New)
- 准备就绪(Runnable)
- 运行(running)
- 阻塞或说等待(Blocked)
- 死亡(Dead)
线程有五种状态,当线程启动,开始运行后,它也不会一直处于运行状态,而是会在就绪,运行,阻塞之间来回切换.
1,2阶段 新建,准备:
一般情况下着两个在代码里总是写一起的.如下code:
1
2
3
4
5
6
7
|
//继承Thread的
new
FirstThread().start();
//实现runnable的
new
Thread(fr,
"newThread11"
).start();
//实现callable的
new
Thread(future,
"有返回值的线程"
).start();
//具体代码参照以前的文章,有的.
|
即使是start也不一定就立即开始执行,如果希望调用子线程的start()方法后立即执行,那么就让主线程沉睡下,Thread.sleep(1).1毫秒就够了,但是如果存在多个子线程,就不好控制了.一般也没必要控制这个.
3.4阶段 运行和阻塞
在线程开始运行后,除非线程执行体足够短,才能直接结束,否则一般情况下都是运行一会,阻塞一会,再运行~~~直到完成.具体机制在于JVM的调度策略.
只有当一个线程调用了它的sleep()和yield()才会放弃所占用的资源--也就是说必须由该线程主动放弃所占用资源.
但发生如下情况.线程会进入阻塞状态:
- 1.线程调用sleep方法,主动放弃处理器资源.(到达规定时间,进入就绪状态)
- 2.调用了一个阻塞式的IO方法,在方法返回前,该线程被阻塞.(返回了..进入就绪)
- 3.线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有.(获得了同步监视器.)
- 4.线程在等待某个通知,notify.(得到通知了)
- 5.程序调用了线程的suspend()方法将线程挂起,但API说这货容易死锁,所以大家不要用.(用resume恢复)
大家需要注意的就是,线程从~~~阻塞-->就绪-->运行-->阻塞-->就绪-->运行~~~,并不是从阻塞直接到运行的.而是阻塞后再次进入就绪状态...
就是这样在3个状态轮回的,但又个例外就是:
yield()方法可以让运行状态的线程直接进入就绪状态.
5.线程死亡
1.run()或call()方法执行完成,线程正常结束.
2.线程抛出一个没有捕获的异常或者错误.
3.直接调用了stop方法来结束线程.(容易死锁,通常不用.)
判断线程是否死亡用isAlive()方法,在就绪,运行,阻塞阶段,返回true.其他新建,死亡阶段为flase.
- 对新建的线程调用2次start方法,是错误的.
- 对死亡的线程调用start方法也是错误的.
- 这2个都会引发 I11egakThreadStateException异常.