java thread 几个状态_图解JAVA线程的几个状态(JAVA笔记-线程基础篇)

Java中线程的状态,是线程在生命周期中不同时间段的状态。举个例子,我们拿小白做作业的例子比作是一条线程要执行的任务。小白掏出作业还没有开始写作业,这就说明线程准备好了。小白开始动笔写了,他在写作业了,他在奋笔疾书的写作业了,这说明线程在运行状态。小白的弟弟小黑把他笔抢去捅蚂蚁洞了,现在小白没法做作业了(他怎么就一个笔?剧情需要....),现在这条线程阻塞状态了也可能是等待状态。小白把小黑揍了一顿,抢来笔继续写作业,现在是线程又是运行状态了。几经波折,小白终于做完了作业了,线程结束。

Java中线程有几种状态

既然谈到线程,怎么离得开Thread这个类。Java中的几个状态也都写在这个类的源码里面了。

在Thread这个类中有一个内部枚举类型。看看源码。

public class Thread implements Runnable {

//省略n多源码...详情看源码

/**

* A thread state. A thread can be in one of the following states:

* 线程状态。一个线程的状态就下面这些了。

*

* 省略n多注释...详情看源码

*/

public enum State {

NEW,

RUNNABLE,

BLOCKED,

WAITING,

TIMED_WAITING,

TERMINATED;

}

//省略n多源码...详情看源码

}

一共6种状态。但是,如果你看过很多大佬画的图,你会发现,他们画的图中,会还有一种是RUNNING的状态?(不信你去百度)但是这个JAVA只有一个RUNNABLE。怎么回事呢?请往下看。

Runnable和Running状态的区别、

为什么大部分JAVA线程状态图里都有RUNNING状态,但是JAVA源码里没有这个状态呢??

因为JAVA没法用代码把线程变成RUNNING状态,他只能让线程是准备好运行的状态RUNNABLE。

不正经举例:

就像妃子们没法控制自己今晚会不会被翻牌(代表RUNNING状态),她们只能准备好被翻牌,也就是RUNNABLE状态。其实CPU也不是同步运行所有线程的,每次它只能运行一个线程,就像每次皇上只能翻一个妃子的牌一样。

CPU只会不断的切换运行的线程,如果切换的足够快,看上去就像是两个线程在同步运行。

(你可以想象一个反复横跳的人,只要他跳的足够快,你看上去也就是有两个人了,好像是影分身。但其实还是只有一个人,不断的挑来跳去罢了,就像CPU不断的切换运行的线程一样。)

结论

running状态对于线程来说是存在的。但是java控制不了,只能把线程变成runable状态。所以源码中也就没有running了。

实在不懂,学习的时候可以把runable和running看成一个状态就好了。或者就看成7种状态。

注意

虽然java无法将runable状态变成runing状态,但是他可以把running状态变成runable状态。。。。。。。。。通过yield();方法。

JAVA线程状态图

下面是要给简单的图,表示这个线程运行的很顺利,走的也很流畅。没有什么复杂的操作。没有什么很复杂的箭头。

cdb91ed2e42ed60b5af432bc2f624cf6.png

下面来个复杂一点点的图

2635040881748f840da15909662f8c3b.png

说明

序号

方法

thread.start()

代码(方法/代码块)被synchronized修饰,线程等待获取锁。

线程获取了锁。

.yield();

.sleep(long);

.wait(long);

.join(long);

LockSupport.parkNanos(long);

LockSupport.parkUntil();

.notify();

.notifyAll();

LockSupport.unpark(thread);

.wait();

.join();

LockSupport.park();

.notify();

.notifyAll();

LockSupport.unpark(thread);

线程里的代码运行结束

线程抛出一个没有捕获的异常或者error

线程各个状态说明和代码实例

NEW

新建状态新建线程对象。

public static void main(String[] args) {

Thread thread=new Thread(new Runnable() {

public void run() {

System.out.println("我是一个新建的线程");

}

});

//通过.getState();可以获取线程状态

System.out.println(thread.getState());

}

输出:NEW

RUNNABLE

运行.start()将线程变成就绪状态,随时准备着被cpu翻牌。

public static void main(String[] args) {

Thread thread=new Thread(new Runnable() {

public void run() {

System.out.println("我是一个新建的线程");

}

});

//start线程

thread.start();

System.out.println(thread.getState());

}

输出:

RUNNABLE

我是一个新建的线程

BLOCKED

线程在等待其他线程把公用的锁对象释放,所以他就一直blocked。就像小白一直等着他弟弟把笔还给他一样。

自定义一个线程类,运行run()方法中要有同步代码块。然后写一个死循环,让代码一直运行,也就一直不释放锁对象。

public class MyThread extends Thread {

private Object clock;

//锁对象

public MyThread(Object clock){

this.clock=clock;

}

@Override

public void run() {

synchronized (clock){

//让这个线程一直运行,所以他就不会释放clock锁给其他线程用

while (true){}

}

}

}

测试代码

public static void main(String[] args)throws Exception {

Object clock=new Object();

//两个线程使用同一个锁对象

MyThread myThread1=new MyThread(clock);

MyThread myThread2=new MyThread(clock);

//启动两个线程

myThread1.start();

myThread2.start();

//为了不断输出线程的状态,我们在主线程里也写要给死循环。这样就能不断输出线程的状态了。

while (true){

System.out.println("myThread1状态是:"+myThread1.getState());

System.out.println("myThread2状态是:"+myThread2.getState());

//没过3秒输出一次

Thread.sleep(3*1000);

}

}

输出

myThread1状态是:RUNNABLE

myThread2状态是:BLOCKED

myThread1状态是:RUNNABLE

myThread2状态是:BLOCKED

myThread1状态是:RUNNABLE

myThread2状态是:BLOCKED

myThread1状态是:RUNNABLE

myThread2状态是:BLOCKED

.......

WAITING

线程进入等待状态,只有其他线程调用⑧中的方法,才会重新进入RUNNABLE状态。

public static void main(String[] args)throws Exception {

Thread thread=new Thread(new Runnable() {

public void run() {

LockSupport.park();

}

});

thread.start();

//同样的套路,把主线程循环,每3秒输出一下线程的状态

while (true){

System.out.println(thread.getState());

Thread.sleep(3*1000);

}

}

输出

RUNNABLE

WAITING

WAITING

WAITING

....

第一个是因为运行太快了,thread线程还没来得及运行完LockSupport.park();主线程就把他状态输出了。

TIMED_WAITING

这个状态跟上面相似,不过这个状态不一定需要别的线程调用notifyAll()这些方法来重新启动线程,在规定的时间后,此状态的线程会自动变成RUNNABLE状态。

注意是不一定需要

将上面的LockSupport.park();改成LockSupport.parkUntil(10*1000);。意识是10秒后自动从TIMED_WAITING变成RUNNABLE。

while (true){

LockSupport.parkNanos(30*1000);

}

输出

RUNNABLE

TIMED_WAITING

TIMED_WAITING

....

TERMINATED

就是线程运行结束了的状态。

直接上代码

public void run1() throws Exception{

Thread thread=new Thread(new Runnable() {

public void run() {

System.out.println("线程运行结束了");

}

});

thread.start();

//主线程休眠1秒,保证thread运行结束

Thread.sleep(1000);

System.out.println(thread.getState());

}

输出:

线程运行结束了

TERMINATED

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值