12、Java多线程:线程的生命周期

2.1 线程的生命周期

线程的生命周期指的是线程对象的生老病死,及线程的状态。

线程生命周期可以通过getState()方法获得,线程的状态是Thread.State枚举类型定义的,由以下几种组成:

NEW        //新建状态。创建了线程对象,在调用start()启动之前的状态

RUNNABLE   //可运行状态,它包括READY和RUNNING两个状态。READY状态表示线程可以被线程调度器进行调度,来使它变成RUNNING状态。RUNNING状态表示该线程正在被执行。Thread.yield()方法可以把线程由RUNNING状态转换为READY状态。

BLOCKED //阻塞状态。线程发起阻塞的IO操作,或者申请由其他线程占用的独占资源,线程会转化为BLOCKED阻塞状态。处于阻塞状态的线程不会占用CPU资源。当阻塞IO操作执行完,或者线程获得了其申请的资源,线程可以转换为RUNNABLE

WAITING   //等待状态。线程执行了object.wait()或者thread.join()方法,会把线程转换为WAITING等待状态。执行object.notify()方法,或者加入的线程执行完毕,当前线程会转换为RUNNABLE状态。

TIMED_WAITING   //与WAITING状态类似,都是等待状态。区别在于,处于该状态的线程不会无限期地等待。如果线程没有在指定的时间范围内完成期望操作,该线程自动转换为RUNNABLE状态。

TERMINATED   //终止状态。线程结束处于终止状态。

线程状态图:

2.2 多线程编程的优势与存在的风险

多线程编程具有以下优势:

  • 提高系统吞吐量(Throughout)。多线程编程可以使一个进程有多个并发线程在执行操作。
  • 提高用户响应速度。
  • 充分利用多核处理器资源。

多线程编程存在的风险:

  • 线程安全问题。多线程共享数据时,如果没有采用正确的并发访问控制措施,就可能产生数据一致性问题。如读取脏数据,如丢失数据更新。
  • 线程活性问题。由于程序自身的缺陷,或者资源的稀缺性,导致线程一直处于非RUNNABLE状态。常见的活性故障有以下几种:死锁、锁死、活锁、饥饿。
  • 上下文切换。处理器切换线程需要从系统消耗。
  • 可靠性。可能会由一个线程导致JVM意外终止,其他的线程也无法执行。