多线程学习记录,勿喷谢谢
目录
2. Runnable : 可运行线程的线程状态,等待CPU调度或处于运行的线程。
3. Blocked : 线程阻塞等待监视器锁定的线程状态,处于synchronized同步代码块或方法中被阻塞。
6. Terminated : 终止线程的线程状态。线程正常完成执行或异常退出。
1. stop jdk已经弃用 ,建议使用 interrupt()
标志位bug
一、多线程的六种状态
1. New : 尚未启动的线程状态。
2. Runnable : 可运行线程的线程状态,等待CPU调度或处于运行的线程。
3. Blocked : 线程阻塞等待监视器锁定的线程状态,处于synchronized同步代码块或方法中被阻塞。
4. Waiting : 无限期等待状态。
Object.wait 、Thread.join、LockSupport.park
5. Timed Waiting : 有限期等待状态。
Thread.sleep、Object.wait 、 Thread.join 、 LockSupport.parkNanos、LockSupport.parkUntil
6. Terminated : 终止线程的线程状态。线程正常完成执行或异常退出。
二、实例
1. 新建->运行->结束
package com.threadTest.demo2;
public class ThreadType {
public static void main(String[] args) throws InterruptedException {
System.out.println("状态为: 新建 -> 运行 -> 终止 ");
//创建线程对象
Thread thread1 = new Thread(() -> {
//运行状态
System.out.println("调用start后thread的状态为: " + Thread.currentThread().getState().toString());
});
//新建状态
System.out.println("没调用start方法时,thread的状态为"+thread1.getState().toString());
//线程开启
thread1.start();
Thread.sleep(2000);
//终止状态
System.out.println("等待两秒,再看thread1当前状态:"+ thread1.getState().toString());
//thread1.start(); 若线程已经终止后,在调用运行thread1.start(); 会抛出IllegalTheadStateException异常
/**
* 状态为: 新建 -> 运行 -> 终止
* 没调用start方法时,thread的状态为 NEW 新建
* 调用start后thread的状态为: RUNNABLE 运行
* 等待两秒,再看thread1当前状态:TERMINATED 终止
*/
}
}
2. 新建 -> 运行 -> 堵塞 -> 运行 -> 终止
package com.threadTest.demo2;
public class ThreadType {
public static void main(String[] args) throws InterruptedException {
System.out.println("状态为: 新建 -> 运行 -> 堵塞 -> 运行 -> 终止");
//创建线程对象
Thread thread1 = new Thread(() -> {
synchronized (ThreadType.class){
System.out.println("thread当前状态: " + Thread.currentThread().getState().toString());
}
});
// 2个锁使用同一个对象,所以线程会堵塞,
//等下方锁释放后,线程的锁才会执行 从堵塞状态切换到运行状态
synchronized (ThreadType.class){
//新建状态
System.out.println("没调用start方法,thread当前状态"+thread1.getState().toString());
//线程启动
thread1.start();
Thread.sleep(200);//等待200毫秒,让线程执行到锁代码
//堵塞状态
System.out.println("等待200毫秒,再看thread当前状态:"+ thread1.getState().toString());
}
//上方锁释放,线程锁可以运行了
Thread.sleep(3000);//等待3秒,让线程执行
System.out.println("等待3秒,再看thread1当前状态:"+ thread1.getState().toString());
//thread1.start(); 若线程已经终止后,在调用运行thread1.start(); 会抛出IllegalTheadStateException异常
/**
* 状态为: 新建 -> 运行 -> 堵塞 -> 运行 -> 终止
* 没调用start方法,thread当前状态NEW 新建
* 等待200毫秒,再看thread当前状态:BLOCKED 堵塞
* thread当前状态: RUNNABLE 运行
* 等待3秒,再看thread1当前状态:TERMINATED 终止
*/
}
}
3.新建->运行->等待(有限期) ->终止
package com.threadTest.demo2;
public class ThreadType {
public static void main(String[] args) throws InterruptedException {
//状态 : 新建 -> 运行 -> 等待(带时间的等待) -> 终止
System.out.println("状态切换: 新建 -> 运行 -> 等待(带时间的等待) ->运行 -> 终止");
//创建线程对象
Thread thread1 = new Thread(() -> {
try {
//等待1.5秒
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
//新建状态
System.out.println("没调用start方法,thread当前状态"+thread1.getState().toString());
//线程启动
thread1.start();
Thread.sleep(200);//等待200毫秒,让线程执行
//等待
System.out.println("等待200毫秒,再看thread当前状态:"+ thread1.getState().toString());
Thread.sleep(3000);//在等待3秒,让线程执行完成
//终止
System.out.println("等待3秒,再看thread1当前状态:"+ thread1.getState().toString());
//thread1.start(); 若线程已经终止后,在调用运行thread1.start(); 会抛出IllegalTheadStateException异常
/**
* 状态切换: 新建 -> 运行 -> 等待(带时间的等待) ->运行 -> 终止
* 没调用start方法,thread当前状态NEW 新建
* 等待200毫秒,再看thread当前状态:TIMED_WAITING 等待
* 等待3秒,再看thread1当前状态:TERMINATED 终止
*/
}
}
三、线程终止
1. stop jdk已经弃用 ,建议使用 interrupt()
package com.threadTest.demo2;
public class ThreadStop {
private static Integer i = 0;
private static Integer y = 0;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
++i;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("使用interrupt终止程序,抓取InterruptedException,可进行异常处理");
y=20;
}
++y;
});
thread.start();
//休眠1秒 确保++i 成功
Thread.sleep(1000);
//暂停线程
//thread.stop();//错误的终止
// todo stop:i=1y=0 直接终止,没有报异常,无法进行异常处理
thread.interrupt();//正确的终止
//todo interrupt:i=1y=21 将线程执行完成,y=20后 在执行 ++Y 并进入异常处理
/**
* java.lang.InterruptedException: sleep interrupted
* at java.lang.Thread.sleep(Native Method)
* at com.threadTest.demo2.ThreadStop.lambda$main$0(ThreadStop.java:12)
* at java.lang.Thread.run(Thread.java:748)
* 使用interrupt终止程序,抓取InterruptedException,可进行异常处理
* i=1y=21
*/
System.out.println(thread.getState().toString());
//等待10秒 打印 i与y的状态
Thread.sleep(10000);
sout();
}
public static void sout(){
System.out.println("i=" + i + "y=" + y);
}
}
2. 使用标志位
package com.threadTest.demo2;
public class ThreadStop {
//标志位
private static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (flag) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程运行中");
}
System.out.println("线程结束");
});
thread.start();
Thread.sleep(2000);
//更改标志位状态
flag = false;
System.out.println("更改标志位状态,会出现延时生效情况");
Thread.sleep(1000);
System.out.println("线程状态=" + thread.getState().toString());
/**
* 线程运行中
* 更改标志位状态,会出现延时生效情况
* 线程运行中
* 线程结束
* 线程状态=TERMINATED
*
* 或
*
* 线程运行中
* 线程运行中
* 更改标志位状态,会出现延时生效情况
* 线程结束
* 线程状态=TERMINATED
*/
// 这里要注意一下,使用标志位有一个坑,当判断标志位的if语句无法执行时,便无法停止线程
}
}
// 这里要注意一下,使用标志位有一个坑,当判断标志位的if语句无法执行时,便无法停止线程
标志位bug演示
package com.design.domain;
public class FlagBit {
private static volatile boolean bit = true;
public static void main(String[] args) throws InterruptedException {
//创建线程
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("线程执行");
//判断标志位
if (bit) {
try {
// 模拟无限堵塞时间
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程执行完成");
}
};
//开启线程
thread.start();
Thread.sleep(1000);
//更改标志位
bit = false;
//thread.interrupt();
Thread.sleep(1000);
System.out.println("线程状态=" + thread.getState().toString());
//执行结果为:无法中断线程。 建议使用thread.interrupt();
// 因为线程在进入无限堵塞后,无法在执行if判断,所以更改标志位无法结束程序
/** 标志位代码
* 线程执行
* 更改标志位
* 线程状态=TIMED_WAITING 堵塞
* 无法中断
*/
//thread.interrupt(); 方法会中断线程并抛出异常
/**
* 线程执行
* thread.interrupt();中断线程
* 线程执行完成
* java.lang.InterruptedException: sleep interrupted
* at java.lang.Thread.sleep(Native Method)
* at com.design.domain.FlagBit$1.run(FlagBit.java:16)
* 线程状态=TERMINATED
*/
}
}