java并发编程02:线程的状态
线程的生命周期
新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Terminated)5种状态。
定义
Thread 的状态是定义在 Thread 内部的枚举类型。
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
new:新建
l new关键字创建了一个线程之后,该线程就处于新建状态
l JVM为线程分配内存,初始化成员变量值
runnable:运行
Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
就绪:l 当线程对象调用了start()方法之后,该线程处于就绪状态
l JVM为线程创建方法栈和程序计数器,等待线程调度器调度
运行:l 就绪状态的线程获得CPU资源,开始运行run()方法,该线程进入运行状态
Blocked:阻塞
阻塞状态是线程因为某种原因放弃CPU的使用权,暂时停止运行
当发生如下情况时,线程将会进入阻塞状态
l 线程调用sleep()方法主动放弃所占用的处理器资源
l 线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
l 线程试图获得一个同步锁(同步监视器),若该同步锁被其他线程占用,则JVM会吧该线程放入“锁池”中。
l 线程在等待某个通知(notify)
l 程序调用了线程的suspend()方法将该线程挂起。但这个方法容易导致死锁,所以应该尽量避免使用该方法
Java中实现线程阻塞的5种方法
(1)线程睡眠:Thread.sleep (long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。sleep()平台移植性好。
(2)线程等待:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池中”。进入这个状态后是不能自动唤醒的,必须依靠其他线程调用notify()或者notifyAll()方法才能被唤醒。
(3)线程礼让,Thread.yield() 方法,暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程.
(4)线程自闭,join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。
(5)Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!
Terminated:死亡
线程会以如下3种方式结束,结束后就处于死亡状态:
l run()或call()方法执行完成,线程正常结束。
l 线程抛出一个未捕获的Exception或Error。
l 调用该线程stop()方法来结束该线程,该方法容易导致死锁,不推荐使用。