线程状态
1、五大状态:
- 新生状态
- 就绪状态
- 运行状态
- 阻塞状态
- 死亡状态
1.1、新生状态
当线程被创建以后即进入新生状态,表示线程可执行
1.2、就绪状态
导致线程进入就绪状态的原因:
- 调用了start()方法
- 阻塞状态解除
- 调用yield()方法,线程中断一下,让出对cpu的占用
- jvm本身将cpu切换到其他线程
1.3、运行状态
运行状态一定是被cpu调度到,线程进入运行状态
1.4、阻塞状态
导致线程进入阻塞状态的原因:
- 调用sleep()方法(占用资源)
- 调用wait()方法(不占用资源)
- 别的线程调用join()方法,插队
- I/O操作,需等待操作系统调度
1.5、死亡状态
让线程进入死亡状态的途径:
- 线程正常执行结束
- 调用stop()、destroy()方法,强制结束线程(已被JDK废弃,强烈不推荐)
2、终止线程
终止线程的两种方式
-
线程正常执行完毕
-
外部干涉 --> 加入标识
!! 不用使用stop、destroy方法 !!
package com.tsymq.thread.threadstate;
public class TerminateThread implements Runnable{
// 加入标识,标记线程体是否可运行
private boolean flag = true;
private String name;
public TerminateThread(String name) {
this.name = name;
}
@Override
public void run() {
int i = 0;
// 关联标识,true --> 运行 false --> 停止
while (flag){
System.out.println(name + ">" + i++);
}
}
// 对外提供方法改变标识
public void terminate(){
this.flag = false;
}
public static void main(String[] args) {
TerminateThread tt = new TerminateThread("tsymq");
/* 新生状态 就绪状态 */
new Thread(tt).start();
for (int i = 0; i < 99; i++) {
if (i == 20){
tt.terminate(); // 终止线程tt
}
System.out.println("主线程 > " + i);
}
}
}
3、暂停线程(sleep)
- sleep(时间)指定当前线程阻塞的毫秒数
- sleep存在InterruptedException
- sleep时间到后线程进入就绪状态
- 模拟网络延迟(黄牛抢票)
- 模拟倒计时
sleep的时候线程不会释放资源,仍然占用
sleep时间结束后,线程进入就绪状态
4、礼让线程(yield)
- 礼让线程,让当前正在执行的线程暂停
- 不阻塞线程,而是将线程从运行状态直接转为就绪状态
- 让cpu重新调度以执行
线程yield后,将会释放cpu资源
package com.tsymq.thread.threadstate;
public class YieldThread {
public static void main(String[] args) {
MyYield my = new MyYield();
new Thread(my, "a").start();
new Thread(my, "b").start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "线程执行中" + i);
if (i % 20 == 0){
System.out.println(Thread.currentThread().getName() + "线程礼让" + i);
Thread.yield();
}
}
}
}
class MyYield implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + "线程执行中" + i);
}
}
}
5、线程插队(join)
- join:合并线程,插队线程
- join()方法写在哪个线程中,哪个线程就被阻塞
package com.tsymq.thread.threadstate;
public class JoinThread {
public static void main(String[] args) {
new Thread(new Dad()).start();
}
}
class Dad extends Thread{
@Override
public void run() {
System.out.println("想抽烟,发现没了\n让儿子去买烟");
Thread t = new Thread(new Son());
t.start();
try {
t.join(); // join卸载Dad的线程体中,Dad被阻塞
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("儿子走丢了,老爸出去找儿子");
}
System.out.println("老爸接过烟,把零钱给了儿子");
}
}
class Son extends Thread{
@Override
public void run() {
System.out.println("拿到老爸的钱...\n路边有游戏厅,玩了10秒");
for (int i = 0; i < 10; i++) {
System.out.println((i+1) + "秒过去了");
try {
Thread.sleep(1000);
} catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("赶紧去买烟\n买到一包中华拿回去");
}
}
6、观察线程状态
线程状态在Thread类中有定义的枚举:
- NEW
- RUNNABLE
- BLOCK
- TIMED_WAITING
- TERMINATED
package com.tsymq.thread.threadstate;
import java.lang.Thread.State;
public class AllThreadState {
public static void main(String[] args) {
Thread t = new Thread( () -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程内容...");
}
});
// 观察状态
State state = t.getState();
System.out.println(state); // NEW
t.start();
state = t.getState();
System.out.println(state); // RUNNABLE
while (state != State.TERMINATED){
// 活动的线程数
int tCount = Thread.activeCount();
System.out.println(tCount);
state = t.getState();
System.out.println(state); // TIMED_WAITING
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
state = t.getState();
System.out.println(state); // TERMINATED
}
}