目录
1、线程的六种状态定义
①New(新建状态):尚未启动的线程的线程状态。
(通俗的说就是我们写了一个线程,还未调用start方法去启动这个线程)
②Runnable(可运行状态):可运行线程的线程状态,等待CUP调度。
(通俗讲就是,线程调用了start方法之后进入该状态)。Runnable状态分两种:1、CPU正在执行这个线程;2、CPU随时可以调度执行该线程的状态
③Blocked(阻塞状态):线程阻塞等待监视器锁定的线程状态。或处于synchronized同步代码块或方法中阻塞。
④Waiting(等待状态):等待线程的线程状态。
(等待线程的意思 就是当前线程不执行,一直等待,直到被其他线程状态唤醒之后,会去继续执行的状态。需要依赖另外的线程调度通知的,通知你了才可以继续执行了)
不带超时的方式:Object.wait、Thread.join、LockSupport.park
⑤Timed Waiting(定时等待状态):具有指定等待时间的等待线程的线程状态。
线程调用下面带超时时间的方法进入等待状态,就会有一个等待时间。超过这个等待时间,线程会抛出异常或者继续执行
带超时的方式:Thread.sleep、object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil
⑥Terminated(终止状态):终止线程的线程状态。线程正常完成执行或出现异常。
在java的jdk里面定义的状态:java.lang.Thread.Statue
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;
}
2、线程的六种状态之间的切换流程图
①第一种状态切换:首先一个线程被创建出来,它是New(新建状态)。调用start方法开始的时候,进入Runnable(可运行状态)。这时候和其他线程抢锁,没抢到,则进入等待Blocked(阻塞状态)。如果你抢到了锁之后,又进入了Runnable可运行状态。
②第二种状态切换:在Runnable(可运行状态)的线程,进入Waiting(等待状态),等待其他线程的通知。该线程收到通知,继续执行,才会重新进入Runnable(可运行状态)。收不到通知就会一直处于Waiting(等待状态),等待执行的状态。
②第三种状态切换:在Runnable(可运行状态)的线程,进入有超时时间的TimedWaiting(定时等待状态),等待其他线程的通知。TimedWaiting(定时等待状态)会有两种情况可以切换回Runnable(可运行状态)。1、等待超时,等了很久没有收到通知,自己进入Runnable(可运行状态)。2、收到通知,继续执行,进入(Runnable可运行状态)
②第四种状态切换:在Runnable(可运行状态)的线程,正常执行结束或者异常的时候,进入Terminated(终止状态)
3、代码演示:
第一种状态切换 - 新建 -> 运行 -> 终止
public class text {
public static void main(String[] args) throws Exception {
// 第一种状态切换 - 新建 -> 运行 -> 终止a
System.out.println("#######第一种状态切换 - 新建 -> 运行 -> 终止################################");
//创建线程thread1
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//线程启动之后,打印线程当前状态
System.out.println("thread1当前状态:" + Thread.currentThread().getState().toString());
System.out.println("thread1 执行了");
}
});
//创建完线程,再调用start方法启动之前,打印线程当前状态
System.out.println("没调用start方法,thread1当前状态:" + thread1.getState().toString());
//线程开始启动
thread1.start();
//等待两秒,等待thread1线程执行结束。再看thread1的状态
Thread.sleep(2000L);
System.out.println("等待两秒,再看thread1当前状态:" + thread1.getState().toString());
// thread1.start(); TODO 注意,线程终止之后,再进行start调用,会抛出IllegalThreadStateException异常
}
}
控制台打印:
第二种:新建 -> 运行 -> 等待 -> 运行 -> 终止(sleep方式)
public class text {
public static void main(String[] args) throws Exception {
System.out.println("############第二种:新建 -> 运行 -> 等待 -> 运行 -> 终止(sleep方式)###########################");
//新建线程thread2
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {// 将线程2移动到定时状态,1500毫秒之后自动唤醒
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2当前状态:" + Thread.currentThread().getState().toString());
System.out.println("thread2 执行了");
}
});
//线程启动之前,打印当前线程thread2状态
System.out.println("没调用start方法,thread2当前状态:" + thread2.getState().toString());
//线程thread2启动
thread2.start();
//打印当前线程thread2的状态
System.out.println("调用start方法,thread2当前状态:" + thread2.getState().toString());
//主方法main等待200毫秒,让线程thread2执行,再看thread2的线程状态
Thread.sleep(200L);
//线程thread2只要执行,线程thread2调用sleep方法,就会进入定时状态,1500毫秒之后,自动唤醒
System.out.println("等待200毫秒,再看thread2当前状态:" + thread2.getState().toString());
// 主线程main方法再等待3秒,让thread2执行完毕,再看状态
Thread.sleep(3000L);
System.out.println("等待3秒,再看thread2当前状态:" + thread2.getState().toString());
}
}
控制台打印:
第三种:新建 -> 运行 -> 阻塞 -> 运行 -> 终止
public class Text {
public static void main(String[] args) throws Exception {
System.out.println("############第三种:新建 -> 运行 -> 阻塞 -> 运行 -> 终止###########################");
//创建线程3
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
//线程thread3执行,去抢Text这把锁。但是锁是主线程的 抢不到。这段期间它的状态就是阻塞状态
// 主线程执行完毕,释放Text锁,thread3这个线程才能拿到锁,往下执行
synchronized (Text.class) {
System.out.println("thread3当前状态:" + Thread.currentThread().getState().toString());
System.out.println("thread3 执行了");
}
}
});
//当thread2、thread3两个线程本创建之后。当前主线程拿到Text锁
synchronized (Text.class) {
//未开启thread3,
System.out.println("没调用start方法,thread3当前状态:" + thread3.getState().toString());
//开启线程thread3
thread3.start();
//线程thread3刚启动,还未抢到锁。打印状态
System.out.println("调用start方法,thread3当前状态:" + thread3.getState().toString());
// 主线程等待200毫秒,再看thread3的线程状态
Thread.sleep(200L);
System.out.println("等待200毫秒,再看thread3当前状态:" + thread3.getState().toString());
}
//这里主线程就释放Text锁啦
// 主线程再等待3秒,让thread3执行完毕,再看状态
Thread.sleep(3000L);
//thread3 拿到锁,执行完毕了 打印状态
System.out.println("等待3秒,让thread3抢到锁,再看thread3当前状态:" + thread3.getState().toString());
}
}
控制台打印:
总结:
通过下面的流程图,通过调用api来切换不同的流程状态