1.安全退出线程
1>设置退出标识
public class SetFlagTest extends Thread {
public volatile boolean exit = false;
@Override
public void run(){
while (!exit){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程执行中。。。");
}
System.out.println("子线程退出");
}
public static void main(String[] args) throws InterruptedException {
SetFlagTest setFlagTest = new SetFlagTest();
setFlagTest.start();
System.out.println("主线程休眠3秒");
sleep(3000);
System.out.println("join() 代表让子线程执行完之后,才执行当前线程后续代码");
/*setFlagTest.join();*/
System.out.println("线程退出");
}
}
打印结果(子线程会一直执行,且可以看得出主线程和子线程互不影响执行)
主线程休眠3秒
子线程执行中。。。
子线程执行中。。。
join() 代表让子线程执行完之后,才执行当前线程后续代码
线程退出
子线程执行中。。。
子线程执行中。。。
子线程执行中。。。
子线程执行中。。。
子线程执行中。。。
修改标识以后就可以执行完,代码如下:
public class SetFlagTest extends Thread {
public volatile boolean exit = false;
@Override
public void run(){
while (!exit){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程执行中。。。");
}
System.out.println("子线程退出");
}
public static void main(String[] args) throws InterruptedException {
SetFlagTest setFlagTest = new SetFlagTest();
setFlagTest.start();
System.out.println("子线程已经开启");
System.out.println("主线程休眠3秒");
sleep(3000);
setFlagTest.exit=true;
System.out.println("修改退出标志");
System.out.println("join() 代表让子线程执行完之后,才执行当前线程后续代码");
setFlagTest.join();
System.out.println("线程退出");
}
}
打印结果如下
子线程已经开启
主线程休眠3秒
子线程执行中。。。
子线程执行中。。。
修改退出标志
join() 代表让子线程执行完之后,才执行当前线程后续代码
子线程执行中。。。
子线程退出
线程退出
但是当当前线程处于阻塞时,使线程处于不可运行状态,即使主线程为该现成设置退出标记位为true
但该线程此时根本无法检测循环标志,因此也无法立即终止
代码验证如下:
注:Thread.currentThread().join();的意思是等待当前线程执行完成再执行(相当于一个死循环的逻辑)
public class BlockSetFlagTest extends Thread {
//退出标识
public volatile boolean exit = false;
@Override
public void run(){
while (!exit){
try {
System.out.println("子线程阻塞之前");
Thread.currentThread().join();
} catch (InterruptedException e) {
System.out.println("子线程阻塞。。。");
e.printStackTrace();
}
}
System.out.println("子线程执行完成");
}
public static void main(String[] args) throws InterruptedException {
BlockSetFlagTest blockSetFlagTest = new BlockSetFlagTest();
System.out.println("开启子线程");
blockSetFlagTest.start();
System.out.println("中断主线程。。。");
sleep(3000);
System.out.println("修改flag...");
blockSetFlagTest.exit = true;
System.out.println("主线程结束");
}
}
打印结果可以看到子线程处于阻塞中,且没有打印”子线程执行完成“这句话因此可以验证上面观点
2.想要让以上线程终止(运行完成),可以在主线程里面增加一个中断,使得子线程抛出异常捕获
代码如下:
public class BlockSetFlagTest extends Thread {
//退出标识
public volatile boolean exit = false;
@Override
public void run(){
while (!exit){
try {
System.out.println("子线程阻塞之前");
Thread.currentThread().join();
} catch (InterruptedException e) {
System.out.println("子线程阻塞。。。");
e.printStackTrace();
}
}
System.out.println("子线程执行完成");
}
public static void main(String[] args) throws InterruptedException {
BlockSetFlagTest blockSetFlagTest = new BlockSetFlagTest();
System.out.println("开启子线程");
blockSetFlagTest.start();
System.out.println("中断主线程。。。");
sleep(3000);
System.out.println("修改flag...");
blockSetFlagTest.exit = true;
System.out.println("让子线程中断");
blockSetFlagTest.interrupt();
System.out.println("主线程结束");
}
}
代码执行结果如下:
开启子线程
中断主线程。。。
子线程阻塞之前
修改flag...
让子线程中断
主线程结束
子线程阻塞。。。
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1245)
at java.lang.Thread.join(Thread.java:1319)
at ThreadStudy.stopTread.BlockSetFlagTest.run(BlockSetFlagTest.java:16)
子线程执行完成
Process finished with exit code 0
3.废弃的线程终止方式(不推荐使用)
1> Tread.stop()
源码中已经清楚废弃这个方法
这个方法强行终止线程,是很危险的,类似于电脑突然被拔电源,而不是正常关机,产生不可预料的后果。
这个方法会强制释放子线程所有的锁,导致被保护的资源出现线程安全
这个方法调用以后,创建的子线程会抛ThreadDeath这个Error
2> Tread.suspend()
使得线程暂停
不会释放类似锁这种资源,也是很危险的
3>Tread.resume()
使得线程恢复
如果在调用resume()方法之前,没有调用suspend(),则不会起作用
suspend()和resume()必须成对出现,否则会出现死锁
4>Runtime.runFinalizersOnExit()
这个方法本身就是不安全的
它可能导致终结器(finalizers)被在活跃对象上被调用,假如其他线程正在操作这个对象会有问题,而且,这个调用不是“线程安全的”,因为他设置了一个VM全局标志