继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

多线程

婧婧安静
关注TA
已关注
手记 21
粉丝 0
获赞 3

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全局标志

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP