JAVA多线程的interrupt()方法介绍

这篇文章再来讲一些JAVA多线程中不常用,但是实际上又很重要的一些小方法,如果对多线程的其他知识有兴趣,可以翻看我的其他文章,兴许能够对您的多线程的学习添砖加瓦~

再说interrupt()方法前,我想给大家介绍一下线程的结束的原理帮助大家来深刻的理解一下interrupt()方法的出现

中断结束的原理

我们理论上只需要让run()停止运行,那么线程就结束了
我看了网上很多其他大佬写的帖子,基本上一上来就给大家写一个while()或者for()循环,然后在里面写interrup()来停止
事实上确实是,我写的帖子主要是针对初学者,我相信大佬也不需要看我的帖子了
我随意从网上赋值一下大佬写的示例代码(如有冒犯,实属抱歉,只是为了把原因说清楚):

public class ThreadTest implements Runnable {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new ThreadTest());
        thread.start();
        Thread.sleep(500);
        thread.interrupt();
    }

    @Override
    public void run() {
        while (true) {
            try {
                System.out.println("try:"+Thread.currentThread().isInterrupted());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("catch:"+Thread.currentThread().isInterrupted());
            }
        }
    }
}

网上大部分大佬的帖子都是类似的,用了一个循环然后来打断循环,为什么要使用循环,原因也很简单

线程的提出主要就是针对循环等费时间的程序,如果是顺序执行代码,单线程完全可以自己实现,没有什么必要写多线程

只要原因了,我也会在下面的示例代码中用循环操作

既然是循环操作,那么是不是意味着我们如果能够把线程中的循环等费时操作给打断,那么线程不就可以很快结束了吗?顺寻执行代码速度很快,大家没意见吧。

在没有引入interrupt()的情况下,我们来打断线程

/*
 需求:通过改变标记来停止线程的运行
 */
public class interruptDemo implements Runnable{
    private boolean flag=true;
    
    public void run() {
        int count=0;
        while(flag)
        {
            System.out.println("I am run!"+count++);
        }
        System.out.println("over");
    }
    void setflag(boolean flag) {
        this.flag=flag; 
    }
    
}
import java.util.LinkedList;

public class TestDemo {
    public static void main(String[] args) {
        interruptDemo in=new interruptDemo();
        Thread t=new Thread(in);
        t.start();
    for(int i=0;i<100;i++)
    {
        System.out.println("I am main"+i);
    }
    in.setflag(false);
    }
}

大家可以试试,运行会很完美,线程执行一半就会停止下来,我们已经成功的通过改变标记来停止线程了

wait()等方法剥夺CPU

当然其实并不是所有的线程都可以这样子停止
比如说这样

/*
 需求:通过改变标记来停止线程的运行
 */
public class interruptDemo implements Runnable{
    private boolean flag=true;
    
    public void run() {
        function(); 
    }
    synchronized void function() 
    {
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        int count=0;
        while(flag)
        {
            System.out.println("I am run!"+count++);
        }
        System.out.println("over");
    }
    void setflag(boolean flag) {
        this.flag=flag; 
    }
    
}

这里把子线程的打印单独拎出来了,然后再加了this锁,保证每次只有一个线程进行访问,里面加了wait()方法,运行到了wait()就会挂起,被剥夺了执行权限

很显然这种情况下,我们没办法把子线程停止,它会一直挂起

本质原因在于子线程被剥夺了执行资格(CPU),没办法继续执行

所以我们的办法就是我们要让它再次恢复资格

这才是真正为什么要引出interrupt()的根本原因

interrupt()

对于线程的执行,大家都很清楚最基本的三个状态:就绪、运行、结束,分别对应的方法是start()、run()、stop()
但是很遗憾由于stop()存在一些安全问题,已经过时弃用了,那么我们需要找出一种合适的方法来代替stop()
interrupt()的功能就是让线程再次获得执行权限,打断wait、join()、sleep()等方法
最终的代码会是这样子

/*
 需求:通过改变标记来停止线程的运行
 */
public class interruptDemo implements Runnable{
    private boolean flag=true;
    
    public void run() {
        function(); 
    }
    synchronized void function() 
    {
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            System.out.println("我被打断了");//wait()打断后会抛出异常
        }
        int count=0;
        while(flag)
        {
            System.out.println("I am run!"+count++);
        }
        System.out.println("over");
    }
    void setflag(boolean flag) {
        this.flag=flag; 
    }
    
    
}
public class TestDemo {
    public static void main(String[] args) {
        interruptDemo in=new interruptDemo();
        Thread t=new Thread(in);
        t.start();
    for(int i=0;i<100;i++)
    {
        System.out.println("I am main"+i);
    }
    in.setflag(false);
    t.interrupt();//打断挂起,让子线程再次获得执行权限
    }
}

这里通过interrupt打断线程的沉睡
网上很多都提到了isinterrupted,这个仅仅是一种标记而已,和flag类似,但是它在抛出后又恢复原来的值
那么使用interrupted就是这样的

/*
 需求:通过改变标记来停止线程的运行
 */
public class interruptDemo implements Runnable{
    private boolean flag=true;
    
    public void run() {
        function(); 
    }
    synchronized void function() 
    {
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            System.out.println("我被打断了");//wait()打断后会抛出异常
        }
        int count=0;
        System.out.println(Thread.interrupted());
        while(Thread.interrupted())
        {
            
            System.out.println("I am run!"+count++);
        }
        System.out.println(Thread.interrupted());
        System.out.println("over");
    }
    void setflag(boolean flag) {
        this.flag=flag; 
    }
    
    
}


public class TestDemo {
    public static void main(String[] args) {
        interruptDemo in=new interruptDemo();
        Thread t=new Thread(in);
        t.start();
    for(int i=0;i<100;i++)
    {
        System.out.println("I am main"+i);
    }
    in.setflag(false);
    t.interrupt();//打断挂起,让子线程再次获得执行权限
    }
}

总结

stop()由于存在安全问题已经弃用
多线程是用来解决某些耗时操作,我们可以通过打断耗时操作来结束线程
interrupt()并不是真正的让线程停下来,它其实只是改变了一下执行标记,最终还是需要我们来完成线程的停止
isinterruped就是一种内部标记和interrupt()配合使用
wait、join()、sleep()剥夺执行权限之后,interrupt可以中断这种挂起

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355