一共六种:
- 初始状态 (NEW) :尚未启动的线程处于此状态。通常是新创建了线程, 但还没有调用 start () 方法;
- 运行状态 (RUNNABLE):Java 线程中将就绪(ready)和运行中 (running)两种状态笼统的称为 "运行中"。比如说线程可运行线程池中, 等待被调度选中,获取 CPU 的使用权,此时处于就绪状态(ready)。 就绪状态的线程在获得 CPU 时间片后变为运行中状态(running)。
- 阻塞状态 (BLOCKED):表示线程阻塞于锁;
- 等待状态 (WAITING):进入该状态的线程需要等待其他线程做出一些特 定动作(通知或中断);
- 超时等待状态 (TIMED_WAITING):进入该状态的线程需要等待其他线 程在指定时间内做出一些特定动作(通知或中断),可以在指定的时间自 行返回;
- 终止状态 (TERMINATED):表示该线程已经执行完毕,已退出的线程处 理此状态
附带面试题:
问:线程状态 RUNNABLE 如何变为 BLOCKED?
答:线程状态变为阻塞有多种原因:可能调用 wait () 方法进入等待池,可能执行同
步方法 / 同步代码块进入等锁池,可能调用了 sleep ()/join () 等待休眠或其他
线程结束,可能发生了 I/O 中断等。
问:为什么要使用线程池?如何使用线程池?线程池有哪些核心参数?初 始化线程池的大小的如何算?shutdown 和 shutdownNow 有什么区别?
答:(1)、降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 (2)、提高响应速度。 当任务到达时,任务可以不需要等到线程创建就能立即执行。 (3)、提高线程的可管理性。 线程是稀缺资源,如果无限制的创建,不仅会消耗 系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控
问:如何使用线程池?
答:工具类 Executors 提供了静态工厂方法以生成常用的线程池:
(1)、newSingleThreadExecutor:创建一个单线程的线程池。如果该线程因为异常而结束,那么会有一个新的线程来替代它。
(2)、newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大值,一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
(3)、newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(默认 60 秒不执行任务) 的线程。当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线 程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM) 能够创建的最大线程大小。
(4)、newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定 时以及周期性执行任务的需求。
问:java 线程池的核心参数?
答:Executors 也提供自定义的线程池构造方法,里面包括七个参数:
public ThreadPoolExecutor ( int corePoolSize, // 常驻线程数,即使空闲时仍保
留在池中的线程数
int maximumPoolSize, // 线程池中允许的最大线程数
long keepAliveTime, // 存活时间。线程数比 corePoolSize 多且处于闲置状态
的情况下,这些闲置的线程能存活的最大时间,为 0 表示会立即回收;
TimeUnit unit, //keepAliveTime 的单位
BlockingQueue workQueue, // 被提交尚未被执行的任务阻塞队
ThreadFactory threadFactory, // 创建线程的工厂
RejectedExecutionHandler handler // 饱和拒绝策略,当队列满了并且线程个数达到 maximunPoolSize 后采取的策略。目前支付四种:AbortPolicy (抛出异常),CallerRunsPolicy (调用者线程处理),DiscardOldestPolicy (直接丢弃任务,不予处理也不抛出异常),DiscardPolicy (默默丢弃,不抛出异常) )