文章目录
线程终止
1.当线程完成任务后,会自动退出。
2.还可以通过使用变量来控制run方法退出的方式停止线程,即通知方式
本质上来说让一个线程终止,办法就一种 让该线程的入口方法执行完毕
方法一 自己创建一个变量来结束循环
代码演示:
package Thread;
public class ThreadDemo9 {
public static boolean isQuit=false;//使用成员变量
public static void main(String[] args) {
//boolean isQuit=false; 变量捕获
Thread t=new Thread(()-> {
long start=System.currentTimeMillis();
while (!isQuit){
System.out.println("hello t");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t 线程终止");
long end=System.currentTimeMillis();
System.out.println("运行时间"+( end-start));
});
t.start();
// 在主线程中, 修改 isQuit
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
isQuit=true;
}
}
方法二 使用Thread内置的标志位
package Thread;
public class ThreadDemo10 {
public static void main(String[] args) {
Thread t=new Thread(()-> {
// currentThread 是获取到当前线程实例.
// 此处 currentThread 得到的对象就是 t
// isInterrupted 就是 t 对象里自带的一个标志位.
while (!Thread.currentThread().isInterrupted()) {
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;//结束循环
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();//把t内部的标志位设置成true
}
}
interrupt方法的作用:
1.设置标志位为true
2.如果该线程正在阻塞中(比如在执行sleep)此时就会把阻塞状态唤醒。通过抛出异常的方式让sleep立即结束
注意一个非常重要的问题
当sleep被唤醒的时候,sleep会自动的把islnterrupted标志位给清空(true->false)
这就导致下次循环,循环仍然可以继续执行了
如果需要结束循环需要在catch中加break
sleep被唤醒机制
如果sleep执行的时候看到isInterrupt标志位是false
sleep正常进行休眠操作
如果当前isInterrupt标志位为true
sleep无论是刚刚执行还是已经执行了一半,都会触发两件事
1.立即抛出异常
2.清空标志位为false再下次循环,到sleep,由于当前标志位本身就是false,就没有影响了
线程插队
1.yield:线程的礼让 让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功
2.join:线程的插队 插队的线程一旦插队成功,则肯定先执行完插入的线程所有的任务
只有确定的方法才让人安心,因此线程插队主要通过join来实现
代码演示:
package Thread;
public class ThreadDemo11 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
System.out.println("hello t");
});
t.start();
t.join();//main线程等待t先结束
System.out.println("hello main");
}
}
在main线程中,调用t.join意思就是让main线程等待t先结束,再往下执行
1.main线程调用t.join的时候,如果t还在运行,
此时main线程阻塞,直到t执行完毕(t的run执行完了),main才从阻塞中解除,才继续执行
2.main线程调用t.join的时候,如果t已经结束了,
此时join不会阻塞,就会立即往下执行
线程的状态
新创建状态 new
新创建了一个线程对象,但还没有调用start()方法
运行状态 runnable
Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”
阻塞状态 blocked
阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态
等待状态 waiting
处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒(调用notify方法或notifyAll方法),否则会处于无限期等待的状态
超时等待状态 timed_waiting
处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒
终止状态 terminated
表示该线程已经执行完毕
当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了