Thread类位于rt.jar下的java.lang包中的一个类,从jdk1.0就已经存在的一个类,可以看出其悠久的历史,可能已经被无数人介绍过了,但是为何今天还要再一次进行介绍,别人的永远是别人的,只有自己真真正正的思考过,梳理过才能消化为自己的,我觉得这是一次内化的过程。
/**
* A thread state. A thread can be in one of the following states:
*
* - {@link #NEW}
* A thread that has not yet started is in this state.
*
* - {@link #RUNNABLE}
* A thread executing in the Java virtual machine is in this state.
*
* - {@link #BLOCKED}
* A thread that is blocked waiting for a monitor lock
* is in this state.
*
* - {@link #WAITING}
* A thread that is waiting indefinitely for another thread to
* perform a particular action is in this state.
*
* - {@link #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.
*
* - {@link #TERMINATED}
* A thread that has exited is in this state.
*
*
*
*
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*
* @since 1.5
* @see #getState
*/
由于本人英文不是特别好,所以这里边别写博客,边对英文文档做些翻译,如有不正确,请指教,谢谢各位
在jdk1.8中 介绍了 State 是从jdk1.5之后被引入的一个概念,一个线程可能是如下几个状态之一
词汇解读: given 指定的,已经安排好的,特定的 reflect 反映,表明,显示
最后这段话中还明确的指出,一个线程在指定的时间点只会处于某一个状态(这说明,这些状态是属于互斥事件,某个线程不可能同时拥有两个状态),这些状态是虚拟机的状态,而不能反映出任何操作系统线程的状态。
在jdk1.8中,线程被定义成枚举类型的六种状态,分别是NEW , RUNABLE , BLOCKED , WAITING , TIMED_WAITING , TERMINATED
/**
* Thread state for a thread which has not yet started.
*/
一个还没开始线程的状态,也就是调用start方法前的状态
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
词汇: processor 处理器; 处理机
可运行线程的线程状态,一个现在在可运行状态是指正在JVM中执行但是还在等待来自操作多系统的其他资源,例如
处理器。
jdk1.8里面已经明确指出,Thread 的 RUNABLE状态是在 JVM 中正在执行,但是在执行过程中,还需要获取来自操作系统的资源,比如处理器,这就意味着,即使处于RUNABLE状态也有可能发生等待,而等待发生的位置确实JVM中的底层代码内
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
* 线程处于阻塞等待一把监视器锁的状态
* 处于阻塞状态是指等待获得一把监视器锁进入同步代码块/方法 或者 在调用Object.wait() 方法后重新进入
* 同步代码块/方法,(or 后面的这段描述坑我好久,因该是这样理解,举例,在A线程调用wait()方法后,所处 * 线程(A)会释放锁,而当A被notify的时候,A线程会从新进入抢锁的状态,在没抢到锁的时候处于阻塞状态)
*/
词汇 block 大块
这段话表达出如下几个含义。
1.线程处于BLOCK状态的原因之一,是没有获取到监视器锁,还有没有其他原因不能确定
2.reenter代表的重入,有这一点可以看出,锁可以分为可重入锁和不可重入锁
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
*
* - {@link Object#wait() Object.wait} with no timeout
* - {@link #join() Thread.join} with no timeout
* - {@link LockSupport#park() LockSupport.park}
*
*
* A thread in the waiting state is waiting for another thread to
* perform a particular action.
* 线程处于等待状态是指,等待另一个线程去计算指定的动作
*
* For example, a thread that has called Object.wait()
* on an object is waiting for another thread to call
* Object.notify() or Object.notifyAll() on
* that object. A thread that has called Thread.join()
* is waiting for a specified thread to terminate.
* 例如,一个已经调用了Object.wait()的线程 正在等待另一个 调用object.notify()
* 或者 object.notifyAll() 的线程对象。该已经调用 Thread.join()等待指定线程终止。
*
*/
处于等待线程的线程状态
一个线程处于等待状态,是由于调用了如下方法中的一个:
没有超时时间 (调用的是 Object 中的 wait方法 ,而Object 中的 wait 方法调用的是一个 native 方法,这已经超出了Java语言的学习范围,具体的实现就不能得知了,但是wait方法中有描述,这里就不具体介绍了,后面有时间,单独写一篇关于Object(超类的文章))
同样是没有超时时间(调用的却是本类(Thread类)的join方法)
//Thread类中的join方法
/**
* Waits for this thread to die.
* 等到当前线程死亡。
*
* An invocation of this method behaves in exactly the same
* way as the invocation
* 此方法的调用与调用的行为完全相同(这里表达的意识就是调用的是重载方法,并没有做其他任何逻辑操作)
*
*
* {@linkplain #join(long) join}{@code (0)}
*
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* interrupted status of the current thread is
* cleared when this exception is thrown.
* 如果任何线程打断了当前线程。当出现该异常的时候,当前处于打断状态的线程状态被清空
*/
public final void join() throws InterruptedException {
join(0);
}
调用join方法,join方法又调用了重载方法,传了实参0。
词汇: invocation–>调用 behaves–>表现 exactly–>精确地; 准确地; 确切地
接下来,再看下调用的重载方法
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
* millis --> 毫秒
* 超过最大等待毫秒的线程将死亡。如果超时时间是0,意味着永久等待
*
* 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.
*
* conditioned --> 训练;使习惯于;影响(某事发生的方式);
* recommended --> 推荐;举荐;介绍;劝告;建议;
* applications --> 申请;请求;申请书;申请表;(尤指理论、发现等的)应用,运用;涂抹;敷用;施用
* 当前实现使用的是循环调用当前类的wait方法,调用的条件时 当前类的 isAlive方法的返回值。
* 当前类的notifyAll() 被调用的时候,当前线程终止。
* 当应用没有使用 wait(),notify(),或者notifyAll() 在当前线程的实例中, join()被推荐。
* 这段文档描述表达的意识,join()是通过循环调用wait(),而前提是 isAlive()返回的是true
* 当线程实例没有使用wait(),notify(),notifyAll()这些方法的时候,推荐使用join()方法
*
* @param millis
* the time to wait in milliseconds
* 参数 毫秒
* 等待的毫秒时间
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
* negative --> 坏的;有害的;消极的;负面的;缺乏热情的;否定的
* 如果传进来的毫秒数是负数,则抛出改异常
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* interrupted status 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;
}
}
}
isAlive() 为native方法,但可以根据注释理解一下
/**
* Tests if this thread is alive. A thread is alive if it has
* been started and has not yet died.
* 测试如果当前线程是否存活,线程是否存活指的是已经开始但还没结束
*
* @return true
if this thread is alive;
* false
otherwise.
* 如果线程存活返回true,其他情况返回false
*/
public final native boolean isAlive();
拓展内容到这里差不多,还是回到状态解读上吧!
LockSupport类中的park()也会造成线程的等待
/**
* Disables the current thread for thread scheduling purposes unless the
* permit is available.
* Disables --> 使丧失能力;使伤残;使无效;使不能运转
* scheduling --> 安排;为…安排时间;预定;列入,收进(正式目录、清单等中)
* purposes --> 意图;目的;用途;目标;情势的需要;重要意义;有价值的意义
* unless --> 除非;除非在…情况下;若非;如果不
*
* 除非许可证可用,否则出于线程调度目的禁用当前线程。
*
* If the permit is available then it is consumed and the call
* returns immediately; otherwise the current thread becomes disabled
* for thread scheduling purposes and lies dormant until one of three
* things happens:
*
* consumed --> 沉迷…的; 充满…的; 消耗,耗费; 吃; 喝; 饮; 使充满; consume的过去分词和过去式;
* immediately --> 立即;马上;即刻;接近;紧接;附近;紧接地;直接地
* lies --> 躺; 平躺; 平卧; 平放; 处于,保留,保持; 说谎; 撒谎; 编造谎言; 谎言; 位置; 谎话;
* dormant --> 休眠的; 蛰伏的; 暂停活动的
* 如果许可证可用,则立刻使用(许可证),并且立刻返回调用结果
* 否则(许可证不可用)当前线程处于线程调度目的禁用当前线程,知道以下三件事情之一发生:
*
*
*
* - Some other thread invokes {@link #unpark unpark} with the
* current thread as the target; or
* 其他线程以当前线程作为目标调用unpark();或者
*
*
- Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
* 其他线程调用Thread类的interrupt(),interrupt了当前线程;或者
*
*
- The call spuriously (that is, for no reason) returns.
*
* spuriously --> 虚假地
* that is, for no reason --> 也就是说,没有理由
* 调用错误地(也就是说,没有任何原因)返回
*
* This method does not report which of these caused the
* method to return. Callers should re-check the conditions which caused
* the thread to park in the first place. Callers may also determine,
* for example, the interrupt status of the thread upon return.
* report --> 汇报;报告;通报;报道;公布;发表;宣布;(v.) 报道;汇报;报告;记述;调查报告(n.)
* caused --> 使发生;造成;引起;导致
* determine --> 决定
* upon --> 强调数目或数量大
* 此方法不报告这些方法中的哪一个导致该方法,调用方应首先重新检查导致线程停止的条件。
* 调用者需要自己确定,例如,返回时线程的中断状态。
*
*/
public static void park() {
UNSAFE.park(false, 0L);
}
这里看到,最终调用的是UNSAFE的park(),而Unsafe这个类中的 park() ,又是通过native实现的
public native void park(boolean arg0, long arg1);
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* 一个带有特定的等待超时时间的等待线程的状态
* 线程处于超时等待,由于调用了以下几个 特定位置等待时间 方法之一
*
* - {@link #sleep Thread.sleep}
* Thread类的sleep方法
* - {@link Object#wait(long) Object.wait} with timeout
* Object的带有超时时间的wait(long) 方法
* - {@link #join(long) Thread.join} with timeout
* Thread类的带有超时时间的join方法
* - {@link LockSupport#parkNanos LockSupport.parkNanos}
* LockSupport.parkNanos方法
* - {@link LockSupport#parkUntil LockSupport.parkUntil}
* LockSuppor.parkUntil方法
*
*/
/**
* Thread state for a terminated thread.
* The thread has completed execution.
* 停止线程的状态
* 线程已经完成执行
*/
重点描述:上图中的 编号 9 需要特殊关注一下,这里会有一个WAITING --> BLOCKED 状态的转换,这种状态切换的场景简单再来描述下。
当A线程在sync代码块中调用了wait()后,那么,A线程会释放掉锁,此时A线程处于WAITING状态(阻塞状态),当B线程调用notify()后,线程A被唤醒,阻塞状态接触,但是会进入到等待锁的状态,在没有拿到锁从新执行后续代码的这段时间内,线程A是处于阻塞状态的
使用多线程,是借助现代CPU的多核特性,使用空间+资源,换取代码的执行效率,了解线程状态是使用线程的基础,从这里开始,希望自己英文翻译的能力能够有所提高,同时对Java的掌握能更上一个台阶。