java多线程——interrupt终止线程

java中有3种方式能终止正在运行的线程:

1.run()方法运行完成,线程正常退出。

2.使用stop方法强行终止,但此方法已经过期,不推荐使用。

3.使用interrupt标记退出。

对线程使用interrupt怎么停不下来?

class Mythread extends Thread{
    public void run(){
        for(int i = 0; i < 50000; i++){
            System.out.println("i=" + i);
        }
    }
}


public class Main {

    public static void main(String[] args)  {
        try {
            Mythread mythread = new Mythread();
            mythread.start();
            Thread.sleep(2000);
            mythread.interrupt();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

运行结果:

 从运行结果看出,线程并没有被停止,虽然我们用了interrupt方法。为什么会这样呢?因为线程调用此方法后,只是对线程做了标记,告诉线程你应该停下来了。究竟什么时候停下来,还需要被标记线程自己进一步处理。那如何能知道线程被提醒要停下来了呢?有两个方法interrupted()与isInterrupted()。

interrupted():测试当前线程是否被标记。

 class Mythread extends Thread{
    public void run(){
        for(int i = 0; i < 50000; i++){
            System.out.println("i=" + i);
        }
    }
}


public class Main {

    public static void main(String[] args)  {
        try {
            Mythread mythread = new Mythread();
            mythread.start();
            Thread.sleep(2000);
            mythread.interrupt();
            System.out.println("测试当前线程main是否被标记:" + mythread.interrupted());
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

运行结果:


注意:当调用interrupted()测试当前线程后,如果线程之前被标记,则此标记被此方法读取后会被清除,如下:

public class Main {


    public static void main(String[] args)  {
        try {
            Thread.currentThread().interrupt();
            System.out.println("测试当前线程main是否被标记:" + Thread.interrupted());
            System.out.println("测试当前线程main是否被标记:" + Thread.interrupted());
            Thread.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

运行结果:


isInterrupted():测试此线程(调用此方法的线程)是否被标记。

 class Mythread extends Thread{
    public void run(){
        for(int i = 0; i < 50; i++){
            System.out.println("i=" + i);

        }
    }
}


public class Main {

    public static void main(String[] args)  {
        try {
            Mythread mythread = new Mythread();
            mythread.start();
            //Thread.sleep(10);     //此出调用sleep(10) 可能看到下面两个都是false
            mythread.interrupt();
            System.out.println("mythread是否被标记:" + mythread.isInterrupted());
            System.out.println("mythread是否被标记:" + mythread.isInterrupted());
            Thread.sleep(10);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

运行结果:

    注意:刚开始我将main线程中的sleep放在了interrupt前(注释掉的地方),结果两个都是false,被标记的线程运行完成了,即使调用了interrupt ,也会返回false。

那么线程被interrupt标记后,需要让自己停下来

 class Mythread extends Thread{
    public void run(){
        try {
            for (int i = 0; i < 50; i++) {
                if (this.interrupted()) {
                    System.out.println("被标记了,通过抛出异常退出。");
                    throw new InterruptedException();
                }
                System.out.println("i=" + i);
            }
        }catch (InterruptedException e){
            System.out.println("catch");
            e.printStackTrace();
        }
    }
}


public class Main {

    public static void main(String[] args)  {
        try {
            Mythread mythread = new Mythread();
            mythread.start();
            //Thread.sleep(10);   //
            mythread.interrupt();
            System.out.println("mythread是否被标记:" + mythread.isInterrupted());
            System.out.println("mythread是否被标记:" + mythread.isInterrupted());
            Thread.sleep(10);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

运行结果:


 使用stop(不推荐)终止线程

class MyThread{
    private String username = "a";
    private String password = "aa";
    public synchronized String getUsername(){
        return username;
    }
    public synchronized String getPassword(){
        return password;
    }
    synchronized public void print_p_u(String password, String username){
        try {
            this.username = username;
            Thread.sleep(100000);
            this.password = password;
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

class test extends Thread{
    private MyThread myThread;

    public test(MyThread myThread){
        this.myThread = myThread;
    }

    public void run(){
        myThread.print_p_u("b", "bb");
    }
}


public class Main {

    public static void main(String[] args)  {
        try {
            MyThread myThread = new MyThread();
            test t = new test(myThread);
            t.start();
            Thread.sleep(500);
            t.stop();
            System.out.println(myThread.getUsername() + " "
            + myThread.getPassword());
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

运行结果:


     可以发现使用stop来终止线程后,可以立马终止线程,数据同步出现了错误;也可以发现线程被强行stop后,自动释放了持有的锁。

总结:

    使用interrupt来“终止”线程,并不能立马终止线程,需要被标记的线程自己去终止,线程判断是否被标记有interrupted()与isInterrupted()两种方式。 让线程自己去决定何时终止,这样做的好处是线程可以安全的去终止自己,可以避免上述数据不同步的现象发生,在一些与数据库交互的情况下,也可以安全的断开与数据库的连接。最后注意,不管是线程先sleep后,再对其调用interrupt;还是先interrupt,线程再sleep,都会抛出异常。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值