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意外终止,其他的线程也无法执行。