Java 线程 3
来源:互联网 发布:金融数据分析导论 pdf 编辑:程序博客网 时间:2024/06/06 08:47
参考:
Java 线程 0 - 前言
java.lang Enum Thread.State
Java疯狂讲义 - 线程的生命周期
学习 Java
线程的生命周期以及相关的函数
主要内容:
- 线程生命周期
getState
和isAlive
sleep
,yield
和join
interrupt
,isInterrupted
和interrupted
线程生命周期
参考:java.lang Enum Thread.State
A thread state. A thread can be in one of the following states: * NEW - A thread that has not yet started is in this state. * RUNNABLE - A thread executing in the Java virtual machine is in this state. * BLOCKED - A thread that is blocked waiting for a monitor lock is in this state. * WAITING - A thread that is waiting indefinitely for another thread to perform a particular action is in this state. * TIMED_WAITING - A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state. * TERMINATED - A thread that has exited is in this state.
Java
定义线程生命周期共有 6
种状态:
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITED
TERMINATED
各状态变化如下图所示:
NEW
使用 new
关键字创建新线程后,该线程就处于 新建 状态。此时,Java
虚拟机为其分配了内存,并初始化了成员变量
RUNNABLE
调用 start
方法后,线程就处于 可运行 状态。Java
虚拟机为其创建方法调用栈和程序计数器,但是线程是否已经运行取决于 Java
虚拟机线程调度器的调度,也就是说,当线程状态为 RUNNABLE
时,并不确定线程是否已经开始执行 run
方法
当没有足够的处理器资源时,线程调用 start
方法后并不会立即执行 run
方法。此时可以暂停当前线程 1
毫秒,即可让就绪线程立即开始运行
BLOCKED
,WAITING
和 TIMED_WAITING
内部对象锁
参考:《Java核心技术 卷I - 14.5.5 synchronized关键字》
从 Java 1.0
开始,每一个 Java
对象都有一个内部锁。如果方法使用 synchronized
关键字声明,即使用内部对象锁来保护方法。所以,必须先获取对象的内部锁,才能调用该方法
BLOCKED
当一个线程试图获取一个对象的内部锁,但该锁已被其它线程持有,那么,该线程就处于 阻塞 状态,直到其它线程释放该锁,并且线程调度器允许该线程持有,此时线程处于非阻塞状态
WAITING
和 TIMED_WAITING
当线程等待另一个线程通知调度器一个条件(condition
)时,该线程处于 等待 状态
即调用 Object.wait
或者 Thread.join
,或者使用 Lock
和 Condition
时,线程处于等待状态
如果线程除了等待另一个线程的通知外,还会计算等待时间,如果超过一定时间,自动回到 可运行 状态,那么此时线程进入的是 计时等待 状态
带有超时参数的方法:Thread.sleep
,Thread.wait
和 Thread.join
,以及 Lock.tryLock
和 Condition.await
TERMINATED
线程 终止 有两种情况:
- 正常运行
run
方法结束 - 在
run
方法中遇到一个未捕获异常而终止
《Java疯狂讲义 16.3 线程的生命周期》
在 《Java疯狂讲义》
中,将线程生命周期分为 5
个状态:
- 新建(
New
) - 就绪(
Runnable
) - 运行(
Running
) - 阻塞(
Blocked
) - 死亡(
Dead
)
其状态变化图如下图所示:
它将 Java
中的 可运行 状态分为了 就绪 和 运行 状态,等待处理器资源的属于 就绪 状态;已获得资源开始运行 run
方法的属于 运行 状态
将 阻塞/等待/计时等待 合并为 阻塞 状态
里面列出了多个处于阻塞状态的情况:
- 线程调用
sleep
方法主动放弃所占用的处理器资源 - 线程调用了一个阻塞式
IO
的方法,在该方法返回之前,该线程被阻塞 - 线程试图获取一个同步监视器,但该同步监视器被其它线程所占有
- 线程在等待某个通知(
notify
)
由上面可知,情况 1 属于 计时等待 状态,情况 2 属于 等待 状态,情况 3 属于 阻塞 状态,情况 4 属于 等待/计时等待 状态
解除上面处于 阻塞 状态的方法如下:
- 调用
sleep
方法的线程经过了指定时间 - 线程调用的阻塞式
IO
方法已经返回 - 线程成功地获得了试图获取的同步监视器
- 其它线程发出了通知
getState
和 isAlive
getState
和 isAlive
参考:
getState()
isAlive()
判断当前线程生命周期状态,可以使用方法 getState
:
/** * Returns the state of this thread. * This method is designed for use in monitoring of the system state, * not for synchronization control. * * @return this thread's state. * @since 1.5 */public State getState() { // get current thread state return sun.misc.VM.toThreadState(threadStatus);}
判断线程是否存活,使用方法 isAlive
:
/** * Tests if this thread is alive. A thread is alive if it has * been started and has not yet died. * * @return <code>true</code> if this thread is alive; * <code>false</code> otherwise. */public final native boolean isAlive();
sleep
,yield
和 join
sleep
,yield
和 join
参考:
sleep
yield
join
sleep
使用方法 sleep
可以暂停当前执行线程指定时间,调用此方法后,线程从 可运行 状态转向 计时等待 状态,其有两个重载函数:
public static void sleep(long millis) throws InterruptedExceptionpublic static void sleep(long millis, int nanos) throws InterruptedException
通常仅指定暂停毫秒数(其精确性和准确性依赖于系统定时器和调度器)
/** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does not lose ownership of any monitors. * * @param millis * the length of time to sleep in milliseconds * * @throws IllegalArgumentException * if the value of {@code millis} is negative * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown. */public static native void sleep(long millis) throws InterruptedException;public static void sleep(long millis, int nanos)throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis);}
从重载方法实现中可看出,Java
系统仅将暂停时间精确到毫秒级
yield
方法 yield
用于提示系统当前线程愿意放弃处理器资源,回到就绪状态,此时如果没有优先级比当前线程高或者相等的就绪线程的话,系统会重新将处理器资源分配给当前线程
/** * A hint to the scheduler that the current thread is willing to yield * its current use of a processor. The scheduler is free to ignore this * hint. * * <p> Yield is a heuristic attempt to improve relative progression * between threads that would otherwise over-utilise a CPU. Its use * should be combined with detailed profiling and benchmarking to * ensure that it actually has the desired effect. * * <p> It is rarely appropriate to use this method. It may be useful * for debugging or testing purposes, where it may help to reproduce * bugs due to race conditions. It may also be useful when designing * concurrency control constructs such as the ones in the * {@link java.util.concurrent.locks} package. */public static native void yield();
对于调用线程来说,yield
方法的使用并没有改变线程的状态(一直在 Runnable 状态)
join
join
方法有 3
种重载形式:
public final void join() throws InterruptedExceptionpublic final void join(long millis) throws InterruptedExceptionpublic final void join(long millis, int nanos) throws InterruptedException
如果线程 A
在线程 B
中调用了 join
方法,那么线程 B
需要等待线程 A
运行结束或者等待一段时间
public final void join() throws InterruptedException { join(0);}/** * Waits at most {@code millis} milliseconds for this thread to * die. A timeout of {@code 0} means to wait forever. * * <p> This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. * * @param millis * the time to wait in milliseconds * * @throws IllegalArgumentException * if the value of {@code millis} is negative * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown. */public final synchronized void join(long millis)throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } }}public final synchronized void join(long millis, int nanos)throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis);}
从重载方法中可知,最终调用的是 join(long millis)
。如果没有任何参数,表示当前线程需要等待调用线程运行结束;如果有输入时间参数(毫秒单位),那么等待一段时间后即可运行
join
方法使当前线程从 运行时 状态进入 等待/计时等待 状态
interrupt
,isInterrupted
和 interrupted
interrupt
,isInterrupted
和 interrupted
参考:
interrupt
isInterrupted
interrupted
线程中断相关的函数有如下 3
个:
public void interrupt()public boolean isInterrupted()public static boolean interrupted()
其使用场景并没有特别理解,线程对象调用 interrupt()
方法后,仅仅设置了中断位,并没有进一步的操作(进一步的操作需要自己去定义,可以忽略中断,也可以进行其它操作)
而且如果遇到线程处于 阻塞/等待/计时等待 的状态下,还会抛出 InterruptedExcpetion
在知乎上找了几个资料:
线程的中断(interrupt)机制
Java里一个线程调用了Thread.interrupt()到底意味着什么?
- Java线程安全 - 线程(3)
- Java线程同步 3
- Java线程3
- java线程3
- java线程池-3
- Java 线程 3
- Java线程总结(3):线程通信
- Java线程(3)--线程间通信
- java之多线程(3)--线程池&Callable
- Java线程-3:线程栈模型与线程的变量
- Java线程池之FutureTask【Java线程池系列3】
- 读书笔记-java网络编程-3线程-java线程概述
- Java中的线程(3)
- java线程理解(3)
- java线程学习(3)
- java多线程:3、线程通讯
- java多线程:3 线程状态
- Java 线程池学习 Reference: 《创建Java线程池》[1],《Java线程:新特征-线程池》[2], 《Java线程池学习》[3],《线程池ThreadPoolExecutor使用简介
- Struts2学习笔记系列之环境搭建
- 变更三记--把近两天的工作变更整理下~
- SpringMVC原理
- 技术变化那么快,程序员如何做到不被淘汰?
- java学习笔记(9)-Java I/O系统
- Java 线程 3
- 数组指针
- maven 实用插件以及搭建本地仓库服务器
- mysql大数据高并发处理(优化)
- [Linux CentOS6.9文件操作系统提示将英文跟换为中文]
- SystemClock
- [NOIP模拟][bzoj 2143][最短路]飞飞侠
- Linux+Nginx+Tomcat实现Web服务器的负载均衡集群
- 算法设计:最大间隙问题