Thread 的各种状态
(1) NEW
/**
* Thread state for a thread which has not yet started.
*/
NEW -- 新建状态
当创建线程后,没有进行start() 操作之前
(2) RUNNABLE
/**
* 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.
*/
RUNNABLE -- 就绪状态,执行状态
执行start()之后,处于就绪状态;当被CPU调度后处于运行状态
(3) BLOCKED
/**
* 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}.
*/
BLOCKED -- 阻塞状态
在进行同步操作,等待锁时会进入该状态(wait, await)
可通过唤醒notify,single 进入RUNNABLE状态
(4) WAITING
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING -- 等待状态
一般执行 wait() other.join()等不加时间参数的方法,
等待的线程需要被唤醒才能继续运行
(5) TIMED_WAITING
/**
* 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:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING -- 时间等待状态
执行sleep(long ) wait(long ) other.join(long )等
时间到了会自动唤醒
(6) TERMINATED
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED -- 终止状态
执行stop() destroy() 或者 run执行结束
关系图如下
Thread 类
(1) 成员变量
//记录线程是否开始,在start()方法中会进行判断,因为一个线程不能同时开启多次
boolean started = false;
private volatile String name; //线程名称
private boolean daemon = false; //是否是守护线程
private Runnable target; //传入的Runnable 对象
private ThreadGroup group; //线程所在线程组
//线程中ThreadLocalMap 对象
ThreadLocal.ThreadLocalMap threadLocals = null;
private long stackSize; //栈大小
private long tid; //线程id
//用来计算的线程id, 其实 id = ++threadseqNumber;
private static long threadSeqNumber;
private volatile int threadStatus = 0; //线程状态
private int priority; //线程优先级 以及 给的优先级的值
/**
* The minimum priority that a thread can have.
* 最小优先级
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
* 默认优先级
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
* 最大优先级
*/
public final static int MAX_PRIORITY = 10;
(2) 构造方法
公有构造方法:
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
Runnable target : 开发者实现的Runnable 对象,start后 会调用target的run方法
String name : 开发者定义的线程名称, 通过Thread.currentThread().getName() 获取
ThreadGroup group : 创建的线程所在线程组,用来对线程进行管理,通过myThread.getThreadGroup().getName()获得,默认main线程
long stackSize : 线程开辟的栈大小
以上8种重载的构造方法中进行如下初始化:
private void init(ThreadGroup g, Runnable target,
String name, long stackSize) {
Thread parent = currentThread();//获得当前线程
//如果开发没有设置线程组,那么设置为默认的,测试过为main 线程
if (g == null) {
g = parent.getThreadGroup();
}
g.addUnstarted(); //线程组未启动的线程数量+1
this.group = g;
this.target = target; //添加runnable
//先将优先级和是否是守护线程定义为线程组的,
//因为开发者可能不通过setPriority setDaemon 方法设置
this.priority = parent.getPriority();
this.daemon = parent.isDaemon();
setName(name); //设置线程名称
init2(parent);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize; //线程栈大小
tid = nextThreadID(); //线程id
}
private void init2(Thread parent) {
this.contextClassLoader = parent.getContextClassLoader();
this.inheritedAccessControlContext
=AccessController.getContext();
//查看当前线程中是否已经存在ThreadLocal,如果有了,
//则将之前使用的ThreadLocal 信息存到本Thread中
if (parent.inheritableThreadLocals != null) {
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(
parent.inheritableThreadLocals);
}
}
私有构造方法:整体和init() 方法一致,但未发现使用在哪里
/** @hide */
// Android-added: Private constructor - used by the runtime.
Thread(ThreadGroup group, String name, int priority,
boolean daemon) {
this.group = group;
this.group.addUnstarted();
// Must be tolerant of threads without a name.
if (name == null) {
name = "Thread-" + nextThreadNum();
}
this.name = name;
this.priority = priority;
this.daemon = daemon;
init2(currentThread());
tid = nextThreadID();
}
构造方法是给Thread 的成员变量group、target、priority、daemon、name、ThreadLocalMap、stackSize、tid 赋值的。
(3) 常用方法
start
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* start 方法存在的原因是:jvm 调用该线程的run 方法
*/
public synchronized void start() {
/**
* A zero status value corresponds to state "NEW".
* 如果不是new 状态,或者已经start了,则抛出异常
*/
// Android-changed: throw if 'started' is true
if (threadStatus != 0 || started)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented.
* 通知group 该线程准备start了,所以添加到group 的集合中,
* 并且group没有start的线程数量递减
*/
group.add(this);
started = false;
try {
//开启线程,传递给底层执行
nativeCreate(this, stackSize, daemon);
started = true;
} finally {
try {
if (!started) {
//start 失败会通知group remove 该线程,
//并group 没有start的线程数量加1
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
//native 方法,调用JNI创建线程传递的是当前线程实例,栈大小,是否守护线程
//所以设置守护线程必须在start()方法之前!!!
private native static void nativeCreate(Thread t, long stackSize,
boolean daemon);
- 判断是否start 多次
- 添加的group 中
- 通知JVM 开启线程
- 开启失败抛出异常
run
Thread 类本身实现Runnable 接口,所以会重写Run方法
@Override
public void run() {
if (target != null) {
target.run();
}
}
- 通过run() 调用,可理解为线程没开启,在线程所在的线程中执行的run方法
- 通过start() 调用,在一个线程的执行方法,执行开发implements Runnable 中的run 方法
注意点:调用start() 和 run() 区别 以及 次数
相同: 调用start 和 run ,都会执行Thread 中的run 方法
不同: start() 真正开启一个线程,并且只能调一次,
否则会java.lang.IllegalThreadStateException 异常;内部通过判断线程状态,!= 0 时抛出异常;run 仅仅是执行一下run 方法,不会创建一个线程,并且可以调用多次。
sleep
字面意思睡觉,不释放当前占用的资源,休眠结束后继续执行;会让出CPU 执行其他任务,睡眠结束后,会再次执行该线程
public static void sleep(long millis) throws InterruptedException {
Thread.sleep(millis, 0);
}
@FastNative
private static native void sleep(Object lock, long millis,
int nanos) throws InterruptedException;
public static void sleep(long millis, int nanos)
throws InterruptedException {
//如果设置的毫秒,纳秒小于0 或者 纳秒 > 999999 表示设置失败,
//抛出IllegalArgumentException 不合法参数异常
if (millis < 0) {
throw new IllegalArgumentException("millis < 0: " + millis);
}
if (nanos < 0) {
throw new IllegalArgumentException("nanos < 0: " + nanos);
}
if (nanos > 999999) {
throw new IllegalArgumentException("nanos > 999999: "
+ nanos);
}
//设置为0 时,没有意义,如果线程中断则抛出中断异常,否则直接返回
if (millis == 0 && nanos == 0) {
// ...but we still have to handle being interrupted.
if (Thread.interrupted()) {
throw new InterruptedException();
}
return;
}
long start = System.nanoTime(); //获得纳秒级时间
long duration = (millis * NANOS_PER_MILLI) + nanos;//睡眠时长
Object lock = currentThread().lock;
// Wait may return early, so loop until sleep duration passes
// 通过计算,判断睡眠时长时候过了,否则一直等待。
//并通过sleep 告诉JVM 该线程处于睡眠状态,run 方法不执行
synchronized (lock) {
while (true) {
sleep(lock, millis, nanos);
long now = System.nanoTime();
long elapsed = now - start;
if (elapsed >= duration) {
break;
}
duration -= elapsed;
start = now;
millis = duration / NANOS_PER_MILLI;
nanos = (int) (duration % NANOS_PER_MILLI);
}
}
}
- 判断输入时间是否异常
- 通过死循环向JVM 更新发送睡眠时间,直到到时退出循环
join
字面意思参加,一个线程中调用other.join(),将等待other执行完后才继续本线程
join方法必须在线程start方法调用之后调用才有意义
public final void join() throws InterruptedException {
join(0);
}
public final void join(long millis, int nanos)
throws InterruptedException {
synchronized(lock) {
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);
}
}
public final void join(long millis) throws InterruptedException {
synchronized(lock) {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value
is negative");
}
if (millis == 0) {
while (isAlive()) {
lock.wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
lock.wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
}
那么在A 线程中调用B.join(), 是如何将A线程停止的呢?
从源码中可以看到,join() 方法中,有wait() 方法。所以在A中,B.join,相当于A 调用了wait() 方法
通过isAlive()来判断B线程是否还在运行,或者通过delay 来判断时间是否到了,如果不满足,wait方法会让A线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限;否则退出join 方法,A线程可重新被调度使用。
yield
字面意思放弃,让出CPU资源,让其他线程使用CPU, 由于不能控制CPU的资源分配,所以可能出现thread让出CPU资源后,又立刻重新调用了。
不会进入阻塞状态 而是进入就绪状态runnable,再次等待被CPU调度
public static native void yield();
interrupt()
中断
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
//看当前线程是否进入阻塞
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
nativeInterrupt();
b.interrupt(this);
return;
}
}
//调用native 方法
nativeInterrupt();
}
private native void nativeInterrupt();
isInterrupted() 判断线程是否中断
public native boolean isInterrupted();
直接使用interrupt()是无法终止的,可以用isInterrupted() 一起使用,来退出循环。
stop 停止
destroy 销毁
This method is inherently unsafe. Stopping a thread with
Thread.stop causes it to unlock all of the monitors that it
has locked (as a natural consequence of the unchecked
<code>ThreadDeath</code> exception propagating up the stack)
过时,线程不安全的,不能释放所有的锁
这个线程本质是不安全的,停止使用该方法的原因是:不能释放所有监视锁
other
setName 设置线程名
getName 获取线程名
setPriority 设置线程优先级
getPriority 获取线程优先级
setDaemon 设置守护线程
isDaemon 判断是否是守护线程
Thread.currentThread() 获得当前线程实例
public static native Thread currentThread();
以上就是Thread 类中主要的内容,有错误就麻烦大家提出来了。
Thanks
~看到新问题会继续补充