线程状态以及切换条件
在正式开始了解线程之前,有一个东西可以关注线程的状态,那就是jconsole,这个东西也并不需要我们再次去下载,因为这个jconsole是Java(JDK)自带的一款图形化监控和管理工具
首先我们得找到我们的JDK装在哪里,找到之后选择bin目录,点进去找到一个名为 jconsole.exe的可执行文件并运行,运行之后我们可以看到下面这张图,我们选择自己要要查看的进程(注意这里的进程必须是正在运行的状态)然后点击连接,进去之后呢,点击左上角的线程,并在这些线程中找到自己要查看的那条线程就好了
线程一共有几种
1.NEW(新建)
- 含义:线程已经被创建,但尚未启动。即调用了
Thread
类的构造方法,但还没有调用start()
方法。
Thread myNewThread = new Thread(()->{
System.out.println("当前线程名称"+Thread.currentThread().getName());
});
System.out.println(myNewThread.getState());
2.RUNNABLE(可运行)
- 就绪: 线程已经获得了所有执行所需资源(比如CPU时间片、内存等),等待CPU调度执行,但可能还没开始运行。
- 运行中: 线程正处于执行状态,正在占用CPU资源进行任务处理。
Thread myRunnableThread = new Thread(()->{
System.out.println("当前线程名称"+Thread.currentThread().getName());
});
myRunnableThread.start();
System.out.println(myRunnableThread.getState());
3.TERMINATED(终止)
- 含义:线程已经执行完毕或因异常终止。
Thread t = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
t.start();
System.out.println("t线程开始执行");
t.join();
System.out.println("t线程执行完毕");
System.out.println(t.getState());
4.WAITING(等待)
- 含义:线程因为调用了
Object.wait()
方法,或者Thread.join()
方法,或者LockSupport.park()
方法,并且没有指定等待时间,导致线程等待。
final Object object = new Object();
Thread t1 = new Thread(()->{
try {
synchronized(object){
System.out.println("wait开始等待");
object.wait();
System.out.println("wait等待结束");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
},"t1");
t1.start();
Thread t2 = new Thread(()->{
synchronized(object){
System.out.println("notify开始执行");
Scanner scanner = new Scanner(System.in);
scanner.next();
object.notify();
System.out.println("notify执行完毕");
}
},"t2");
t2.start();
我们可以用通过 jconsole 来观察到 这个线程状态
当我们执行这段代码,并且在输入环节还未按下Enter键的时候,此时 t1 线程就处于waiting状态
5.TIMED_WAITING(定时等待)
- 含义:与WAITING相似,不过线程在等待一个具体的时间,即调用了带有超时参数的
Object.wait(long timeout)
,Thread.sleep(long millis)
, 或者Thread.join(long millis)
等方法。
final Object object = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(object){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
},"t1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
System.out.println("hehe");
}
}
},"t2");
t2.start();
使⽤ jconsole 可以看到 t1 的状态是 TIMED_WAITING , t2 的状态是 BLOCKED
这里是t1
线程的执行流程:
t1
线程启动,并尝试获取object
对象的锁。- 一旦获取了锁,
t1
线程就会进入一个无限循环,在这个循环中,它会调用Thread.sleep(1000)
。 - 调用
Thread.sleep(1000)
会使t1
线程暂停执行1000毫秒,并且线程的状态会变为TIMED_WAITING
。 - 1000毫秒过后,
t1
线程会自动从TIMED_WAITING
状态变为RUNNABLE
状态,并继续执行循环中的代码。
与此同时,t2
线程也在尝试获取object
对象的锁。但是,由于t1
线程已经持有了这个锁,并且由于无限循环和sleep
调用,它不会很快释放这个锁,所以t2
线程将不得不等待,直到t1
线程释放锁(在这个特定的代码示例中,实际上t1
线程永远不会释放锁,因为它没有退出同步块的路径)。
6.BLOCKED(阻塞)
- 含义:线程在等待监视器锁,以便进入一个同步块或方法。例如,当线程试图获取一个内部的对象锁,而锁被其他线程持有时,线程就会进入BLOCKED状态。
final Object object = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(object){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
},"t1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
System.out.println("hehe");
}
}
},"t2");
t2.start();
此处代码和上面 TIMED_WAITING 的代码是一样的,同理t1 的状态是 TIMED_WAITING , t2 的状态是 BLOCKED,其他的可以参考上面,这里就不过多赘述了
状态之间的切换条件
-
NEW -> RUNNABLE:当调用线程的
start()
方法时,线程状态从NEW变为RUNNABLE。 -
RUNNABLE -> BLOCKED:当线程试图获取一个内部的对象锁,而锁被其他线程持有时。
-
RUNNABLE -> WAITING:当线程调用
Object.wait()
方法,没有指定等待时间。 -
RUNNABLE -> TIMED_WAITING:当线程调用如
Thread.sleep(long millis)
、Object.wait(long timeout)
等带超时参数的方法。 -
WAITING/TIMED_WAITING -> RUNNABLE:当等待条件满足,如
wait()
方法被其他线程调用notify()
或notifyAll()
唤醒,或sleep()
、join()
、park()
超时/被unpark。 -
RUNNABLE -> TERMINATED:当线程执行完毕其
run()
方法,或者线程因未捕获的异常而结束。
原文地址:https://blog.csdn.net/snow_feather/article/details/140569526
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!