首页 > 编程语言 >JUC并发编程基础篇第五章之线程中断状态[你理解的线程中断,只会Thread.interrupted()吗]

JUC并发编程基础篇第五章之线程中断状态[你理解的线程中断,只会Thread.interrupted()吗]

时间:2023-04-07 15:44:32浏览次数:53  
标签:JUC Thread 中断 t1 println 线程 interrupt

目录

1、什么是线程的中断机制

首先 - 线程的中断不应该由其他线程来中断或者停止,而是自己线程中断和停止; 自己决定的命运,所以Thread.stop, Thread.suspend, Thread.resume都废弃了;

其次 - 在java中没法立即停止一个线程,然后停止线程却显得尤为重要

  • java中提供了一种用于停止线程的协商机制 -- 中断, 也即中断标识协商机制
  • 中断只是一种协商机制,java中没有给中断增加任何语法,中断的过程完全由程序员自己实现
  • 若要中断一个线程,你需要手动调用该线程的isterruput方法,该方法也仅仅是把该线程对象的中断标识设置为true
  • 接着你需要自己写代码不断检测当前线程的标识,如果为true,表示别的线程请求这条线程中断,此时做什么,就需要自己写代码了;

每个线程中都有一个中断标识符,用于表示线程是否被中断;该标识符为true 为中断 ,反之 未中断; 通过调用线程对象的interrupt()方法将该线程的标识位设为true; 可以在别的线程中调用, 也可以在自己的线程中调用 通俗解释 : 服务员中断客户的吸烟的操作, 进行提醒而不是直接抢走客户的烟中断这个操作,而是等待客户自己中断吸烟的操作;

2、isterrupt interrupted isInterrupted 区别

方法 含义
isterrupt 实例方法 ; 设置线程的中断状态为true , 发起一个协商而不会立即停止线程
interrupted 静态方法; 判断线程是否被中断 并 清除当前中断状态 (它做了两件事) 1. 返回当前线程的中断状态,测试当前线程是否已经被中断 2. 将当前线程的中断状态清零并且重新设置为false,清除线程的中断状态
isInterrupted 实例方法; 判断当前线程是否被中断 (检查中断标志位) 如果该线程阻塞的时候调用wait(),或者object的join, sleep ,此时他的中断状态会被清除,并且会抛出InterruptedExcepiotn

3、面试题

3.1、 如何停止中断运行中的线程

  • 方法1 通过一个vaoliate变量实现
public class interruputTest {
    private static volatile boolean flag = false;
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (!flag) {
                System.out.println(Thread.currentThread().getName()+线程被中断了);
                break;
            }
            System.out.println(Thread.currentThread().getName()+线程被中断了);
        },a);

        t.start();
        Thread.sleep(2000);
        new Thread(()->{
            flag = true;
        },b).start();
    }
}
  • 方法2 通过AtomicBoolean实现
import java.util.concurrent.atomic.AtomicBoolean;

public class interruputAtomicTest {

    private static AtomicBoolean atomicBoolean = new AtomicBoolean(false);

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (atomicBoolean.get()) {
                System.out.println(Thread.currentThread().getName()+线程被中断了);
                break;
            }
            System.out.println(Thread.currentThread().getName()+线程被中断了);
        },a);

        t.start();
        Thread.sleep(2000);
        new Thread(()->{
            atomicBoolean.set(true);
        },b).start();
    }
}]
  • 方法3 通过Thread类自带的中断api实例方法实现
public class interruputApiTest {

    private static volatile boolean flag = false;
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName()+线程被中断了);
                break;
            }
            System.out.println(Thread.currentThread().getName()+线程被中断了);
        },a);

        t.start();
        Thread.sleep(2000);
        new Thread(()->{
              t.interrupt();
        },b).start();
       ## t.interrupt(); 也可以自己中断
    }
}

3.2、当前线程的中断标识符为true,是不是线程就立马停止了

回答: 不会的, 案例证明

public class interruputDemo1 {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 300; i++) {
                System.out.println(i);
            }
        }, "t1");
        t1.start();
        System.out.println("t1线程刚开始的线程状态为" + t1.isInterrupted());
        t1.interrupt();
        System.out.println("t1线程执行完interrupt的线程状态为" + t1.isInterrupted());
        Thread.sleep(2000);
        System.out.println("t1线程执行完数据的线程状态为" + t1.isInterrupted());
    }
}

输出结果 t1线程刚开始的线程状态为false .... t1线程执行完interrupt的线程状态为true 137 138 ...... t1线程执行完数据的线程状态为false(执行完了,自己就变成了false)

3.3、如果线程处于被阻塞的状态(列入sleep,wait,join等状态),在别的线程调用当前线程的interrupt()方法,会发生什么?

答案: 那么该方法将立即退出阻塞状态,抛出interruputedException异常

示例证明

  public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 300; i++) {
                System.out.println(i);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1");
        t1.start();
        System.out.println("t1线程刚开始的线程状态为" + t1.isInterrupted());
        t1.interrupt();
        System.out.println("t1线程执行完interrupt的线程状态为" + t1.isInterrupted());
        Thread.sleep(2000);
        System.out.println("t1线程执行完数据的线程状态为" + t1.isInterrupted());
    }

在这里插入图片描述

从图中可以看出来,因为虽然抛出了InterruptException但是程序并没有因为打断,而停止运行; 如果想要解决需要添加如下的代码

public class InterruputDemo1 {

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true){
                if (Thread.currentThread().isInterrupted()){
                    System.out.println(Thread.currentThread().getName()+"中断标记为,程序停止");
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println("我在输出哦");
            }
        }, "t1");
        t1.start();
        t1.interrupt();
    }
}

解析

  1. 初始中断标志位是false
    2.t1.interrupt() 中断标志位是true
    3.Thread.sleep(100); 被打印,清除中断标志位是false
    4.Thread.currentThread().interrupt(); 需要再次给他中断标志位设置为true才行

3.4、interrupted的特点

        System.out.println(Thread.currentThread().getName()+"--->"+Thread.interrupted());//false
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.interrupted());//false
        System.out.println("1");
        Thread.currentThread().interrupt();
        System.out.println("2");
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.interrupted()); // 第一此打印真实值,然后清空   true
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.interrupted()); //false

4、 isterrupt和interrupted源码分析

1. interrupt()方法

interrupt() 方法用于中断一个线程,其源码如下:

public void interrupt() {
    if (this != Thread.currentThread()) {
        checkAccess();
    }
    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0(); // If the thread is blocked in an interruptible method.
            b.interrupt(this);
            return;
        }
    }
    interrupt0(); // If the thread is not blocked in an interruptible method.
}

  • interrupt()方法会首先判断当前线程是否是调用interrupt()方法的线程,如果不是则会抛出SecurityException异常。
  • 然后,它会获取锁,检查当前线程是否被阻塞,如果当前线程正在阻塞并且是可中断的阻塞操作,则会调用interrupt0()方法中断该阻塞操作;否则,它会仅仅设置中断标志位为true。
  • 需要注意的是,调用interrupt()方法并不会立即中断线程的执行,它仅仅会设置中断标志位为true,线程需要主动检查中断标志位并做出相应的处理才能有效地中断线程的执行。

2. interrupt()方法

interrupted()方法用于检查当前线程的中断状态,并清除中断标志位。其源码如下:

public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

  • interrupted()方法会返回当前线程的中断状态,并将中断标志位设置为false。需要注意的是,调用interrupted()方法并不会中断线程的执行,它仅仅是检查当前线程的中断状态。
  • 总之,interrupt()方法和interrupted()方法都可以用于中断线程,但是它们的作用有所不同。interrupt()方法可以中断一个线程的阻塞操作,而interrupted()方法则只能检查中断状态并清除中断标志位。在使用中,需要根据具体的情况选择合适的方法来中断线程。

标签:JUC,Thread,中断,t1,println,线程,interrupt
From: https://www.cnblogs.com/itcastwzp/p/17296385.html

相关文章

  • IO流中「线程」模型总结
    目录一、基础简介二、同步阻塞1、模型图解2、参考案例三、同步非阻塞1、模型图解2、参考案例四、异步非阻塞1、模型图解2、参考案例五、Reactor模型1、模型图解1.1Reactor设计原理1.2单Reactor单线程1.3单Reactor多线程1.4主从Reactor多线程2、参考案例六、参考源码IO流模块......
  • Java多线程之共享资源和同步
    一、竞争条件所谓竞争条件,即两个或更多的任务竞争响应某个条件,因此产生冲突或不一致结果的情况。IntGenerator.java生成一个整数:publicabstractclassIntGenerator{privatevolatilebooleancanceled=false;(1)publicabstractintnext();(2)public......
  • Linux(CentOS7) c语言编程, 多线程入栈出栈,错误:expected ‘while’ before ‘int’
    在Centos7里,编写多线程的入栈出栈时,出现这样错误提示:图片版: 文字版:[root@CentOs705-xitongbiancheng]#gcc05-24-01.pthread-cancel-pop-push.c-pthread05-24-01.pthread-cancel-pop-push.c:在函数‘func’中:05-24-01.pthread-cancel-pop-push.c:47:1:错误:expected......
  • 17 同步与互斥(三) 中断屏蔽
    中断处理流程1简介中断屏蔽是一种可以防止并发导致竞态的方法。在进入临界区之前屏蔽系统中断可以保证正在执行的内核路径不被打断(进程调度也依赖于中断)。不过在驱动编程中此方法并不值得推荐。因为驱动并不一定运行在单核上,面对SMP系统中断屏蔽并不能屏蔽掉别的CPU的中断操......
  • Java笔记(11) 多线程
    Java原生支持多线程,主要通过以下四种方式实现多线程:继承Thread类实现Runnable接口实现Callable接口线程池继承Thread类通过创建Thread类的子类,并重写run()方法,通过调用start()方法启动线程。publicclassTestThreadextendsThread{@Overridepublicvoidru......
  • 大意了,一次多线程操作不当导致的线上事故...
    大家好,我是飘渺。今天给大家分享个生产事故,一个由于多线程操作不当导致的线上事故,事情是这样的~事故描述从6点32分开始少量用户访问app时会出现首页访问异常,到7点20分首页服务大规模不可用,7点36分问题解决。整体经过6:58发现报警,同时发现群里反馈首页出现网络繁忙,考虑到前几日晚上......
  • 线程插队Join
    publicclasstest04{publicstaticvoidmain(String[]args)throwsInterruptedException{Qq=newQ();Threadthread=newThread(q);for(inti=0;i<10;i++){Thread.sleep(1000);System.out.println......
  • 子线程中获取父线程的数据(线程池下失效)
    子线程中获取父线程的数据staticInheritableThreadLocal<String>local=newInheritableThreadLocal<>();publicstaticvoidmain(String[]args){local.set("123");System.out.println(Thread.currentThread().getName()+&qu......
  • 线程的常用方法
    1、setName设置线程名称,使之与参数name相同2、getName返回该线程名称3、start使该线程开始执行4、run调用线程对象的run方法5、setPriority更改线程的优先级6、getPriority获取线程的优先级7、sleep通过毫秒来进行线程休眠8、interrupt中断线程......
  • 进程、线程退出方式
    一、进程退出有8种方式使进程终止(termination),其中5种为正常终止:(1)从main返回。(2)调用exit。(3)调用_exit或_Exit。(4)最后一个线程从其启动例程返回。(5)最后一个线程调用pthread_exit。异常终止有3种方式:(6)调用abort。(7)接到一个信号并终止。(8)最后一个线程对取消请求作出响应。......