本系列读《实战java高并发程序设计》有感(03)。
前面说了到如何去创建线程,那当一个线程创建好后,线程的可能经过哪些状态后,最终结束呢?下面就来一起分析分析。
首先,我们打开Thread类的源码,可以看到它里面有一个枚举类State,这个枚举就定义了一个线程可能经历的所有状态。
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* 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,
/**
* 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,
/**
* 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,
/**
* 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,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
从这个枚举中可以看出,一个线程可有状态有:
-
NEW:
创建完并没有启动的时候。
-
RUNNABLE:
在Java虚拟机中执行了,但可能会在等待操作系统资源如处理器调试等。
说白了就是我这个线程已经准备好了,就等你操作系统来调用了。
-
BLOCKED:
阻塞状态,就是等待一个监视器锁,比如B想进入synchronized修饰的代码块或者方法里,而A线程已经进入了该方法中,则B就会进入阻塞状态。
-
WAITING、TIMED_WAITING:
从State枚举的注释中可以看出这两个状态都是在手动调用某些方法时触发的,如果wait()、join()、LockSupport.park()等,区别就是没带时间参数就是WAITING,否则就是TIMED_WAITING。
-
TERMINATED:
代码执行完后,基本上就run方法执行完后。
最近茶馆生意不错,招了个新伙计,通知明天上班,这个新伙计还没正式上班时,就相当于NEW状态,当他准备好了来上班了,进入RUNNABLE状态。新伙计第一天上班有点紧张,一紧张就想上厕所,而当厕所刚好有人的时候,他就只好在门口等了,这时进入BLOCKED状态。这时里面的人说你先等着,或者过5分钟我好了就来叫你,就相当WAITING、TIMED_WAITING状态。最后忙了一天终于下班了,相当于今天的工作就结束了,进入了TERMINATED状态。
当然了上面只是个大概的意思,接下来通过代码来看看线程的各个状态。
- NEW
Thread thread = new Thread(new MyRunnableThread());
System.out.println("thread state:" + thread.getState()); //thread state:NEW
创建一个Thread实例后,没有调用start方法。
- RUNNABLE
Thread thread = new Thread(new MyRunnableThread());
thread.start();
System.out.println("thread state:" + thread.getState()); //thread state:RUNNABLE
调用完start()方法后,进入RUNNABLE状态。
- BLOCKED
public class MyRunnableThread implements Runnable {
@Override
public void run() {
synchronized (this){
System.out.println("我是一个线程" + Thread.currentThread().getName());
while (true){}
}
}
}
Runnable runnable = new MyRunnableThread();
Thread threadA = new Thread(runnable);
threadA.start();
Thread threadB = new Thread(runnable);
threadB.start();
try {
//保证输出时threadB已经被调用了
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread state:" + threadB.getState()); //thread state:BLOCKED
多个线程之前的相互影响,同时进入synchronized块等。
- WAITING/TIMED_WAITING
public class MyRunnableThread implements Runnable {
@Override
public void run() {
try {
Thread.currentThread().join(3000);//实际最终还是调用的wait();
// LockSupport.park();
// Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (this) {
try {
// wait();//wait必须在同步块中
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("我是一个线程" + Thread.currentThread().getName());
}
}
改造一下MyRunnableThread类,调用相应方法就可看到相应状态的输出。
- TERMINATED
Thread threadB = new Thread(()->{System.out.println("finish");});
threadB.start();
try {
//保证输出时threadB已经被调用了
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread state:" + threadB.getState()); //thread state:TERMINATED
通过测试可以看到打印完finish后,再输出thread state:TERMINATED。