线程的状态
状态 | 含义 | 状态转换 |
---|---|---|
新建(New) | new关键字创建一个对象,主要是线程分配内存并初始化成员变量值,结合jvm虚拟机的实现来理解,新建线程需要将线程私有的本地方法区数据初始化好 | - |
就绪状态(Runnbale) | 调用线程的start()方法后的线程状态,结合jvm虚拟机的实现来理解,此时需要将虚拟机栈和程序计数器数据初始化好,此时线程私有的数据均已初始化好等待该线程的调度和运行 | 新建->就绪:调用start()方法; 阻塞->就绪:notify方法唤醒、获得同步锁、sleep时间到、IO方法返回、join线程执行结束; 运行->阻塞:yield方法、失去CPU资源 |
运行状态(Running) | 调用Runnbale接口的run()方法,执行自定义逻辑 | 就绪->运行:得到CPU资源 |
阻塞状态(Blocked) | 运行中的线程主动或被动放弃CPU资源,则线程状态转为阻塞状态,可细分为等待阻塞(wait方法)、同步阻塞(获取锁失败)和其他阻塞(sleep方法、join方法,IO操作)三种 | 运行->阻塞:wait方法、等待同步锁、sleep方法、join方法、发起IO操作 |
死亡状态(Dead) | 线程执行完毕后销毁 | 运行->死亡:正常执行完毕、抛出异常、手动结束(stop) |
线程创建方式
线程池start()方法用于启动线程,run()方法用于执行具体逻辑,不管是通过哪种方式run()方法最终都会在Runnable实现类中寻找run()实现逻辑并调用,因此不管哪种多线程实现方式自定义的实现逻辑都需要重写Runnable的run()方法才可以。
继承Thread类
Thread类实现了Runnable接口,通过**重写run()**方法即可实现自定义逻辑。
实现Runnable接口
实现Runnable接口的run()方法,新建Thread对象将runnable传入即可实现调用自定义run()方法。
通过ExecutorService和Callable实现有返回值的线程
实现Callable接口的call()方法,新建一个线程池调用subnmit()传入callable对象,线程执行结果通过Future对象接收。Future的run()方法会调用call()方法。
基于线程池
新建线程池调用execute()传入Runnable对象,重写run()方法实现自定义逻辑。
线程基本方法
方法 | 作用 |
---|---|
wait | 线程进入阻塞状态(WAITING),并释放对象的锁 |
sleep | 线程进入休眠状态(TIMED-WAITING),不会释放对象的锁 |
yield | 让出CPU资源进入就绪状态,重新竞争CPU |
interrupt | 发出中断信号,将中断标识(用于安全终止线程)变为true,并不会直接变更线程状态,依赖处理流程中对中断标识位的使用。 调用sleep方法的线程在中断标识位true是会抛出异常,在抛出异常前会将标识重新置为false |
join | 等待其他线程终止,调用其他线程的join方法后当前线程会转为阻塞状态,在其他线程执行完毕后当前线程会转为就绪状态 |
notify | 唤醒线程,线程状态由阻塞变为就绪状态 |
setDaemon | 守护线程,生命周期通JVM |
线程池使用
ThreadPoolExecutor方法包含6个核心参数,核心线程数、最大线程数、空闲线程最大存活时间、时间单位、任务队列。
拒绝策略:
- AbortPolicy:直接抛出异常
- DiscardOldestPolicy:丢弃线程队列中组早的线程任务
- DiscardPolicy:丢弃当前线程
- CallerRunsPolicy:调用线程执行
- 自定义拒绝策略