Java线程中的interrupt相关方法一看就会

对于这些一系列的方法,首先得清楚的知道线程运行状态的转换才能更好的去理解。

一个线程声明周期:初始,就绪,运行,阻塞,运行,死亡。


                                                                                                                                        (图为网上找的,侵删!!!)

有三种原因引起阻塞: 等待阻塞、同步阻塞、其他阻塞(睡眠,join,IO阻塞)

在Java的方法中,等待是wait,同步是syn块,睡眠是sleep,join阻塞是join产生的。

一般我们都会说interrupt是中断标志,那么我们详细来说说:

    一个线程不应该由其他线程来强制中断或停止,应该由自己去中断,

    故 Thread.stop, Thread.suspend, Thread.resume都已经废弃了。

Thread.interrupt并不能中断线程,只是通知线程“你应该中断了”。


那么接下来,再来看看差不多的命名方法


查看api可以知道有三个类似的方法。

  


两个区别:

1. interrupted是静态方法,作用与当前线程, isInterrupted作用于调用该方法的线程对象所对应的线程。

线程对象对应的线程不一定是当前运行的线程

2. 这两个方法都是同一个方法,只是参数不一样,看上面注释,就能明白,前者是有清楚标记的作用。

      一般的,通过interrupt和interrupted方法两者的配合可以实现正常去停止一个线程,线程A通过线程B的interrupt方法通知线程B让它结束线程,在线程B的run内部中,循环检测interrupted是否真来接受线程A的信号,如果为真就可以抛出一个异常,在catch中完成清理工作,然后结束线程。

       如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理;例如,一个线程在运行状态中,其中断标志被设置为true,则此后,一旦线程调用了wait、jion、sleep方法中的一种,立马抛出一个InterruptedException,且中断标志被清除,重新设置为false。程序员用try-catch来捕捉Jvm抛出的异常来做各种处理,如何时退出线程。

来看几个例子:

public class Test {

    public static void main(String[] args) {
        Thread t = new Thread(new worker());

        t.start();
        try{
            Thread.sleep(200);   
            //System.out.println(Thread.currentThread().isInterrupted());  表示当前main线程
            //System.out.println(t.isInterrupted());        work子线程
        }catch (InterruptedException e){
            System.out.println("main is exception");
        }

        t.interrupt();
        System.out.println("Main Thread is stopped");
    }
}

class worker extends Thread{
    @Override
    public void run() {
        super.run();
        //System.out.println(Thread.currentThread().isInterrupted());   // 表示的是当前work线程
        System.out.println("work is start");
        try{
            Thread.sleep(500);
        }catch (InterruptedException e){
            System.out.println("work isInterrupted()" +
                    Thread.currentThread().isInterrupted());
        }
        System.out.println("work is stop");
    }
}


    主线程启动一个子线程,让worker线程睡500ms,而main睡200ms,之后main调用work的interrupt方法中断work(通知work你该自己了结了),work被打断了,要知道main的没有抛出异常,work抛出异常了,且中断标志清除了。


public class Test1 {
    public static void main(String[] args) {
        try{
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(200);
            thread.interrupt();
        }catch (InterruptedException e){
            System.out.println("main catch");
        }
            System.out.println("end");
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        super.run();
        try {
            System.out.println("run begin");
            Thread.sleep(200000);
            System.out.println("run end");
        }catch (InterruptedException e){
            System.out.println("在沉睡中停止" + this.isInterrupted());
            e.printStackTrace();
        }
    }
}

把主线程中的interrupt和sleep交换一下,清除执行顺序、 稍微注意一下sleep和interrupt的顺序区别。

停止线程的方法——异常法

public class Test {
    public static void main(String[] args) {
        try{
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(10);      // 时间不要定的太长了,否则直接运行完了还没开始标记中断
            thread.interrupt();
        }catch (InterruptedException e){
            System.out.println("main catch");
        }
            System.out.println("end");
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        super.run();
        try {
           for(int i = 0; i < 50000; i ++){
               if(Thread.interrupted()){
                   System.out.println("停止了");
                   throw new InterruptedException();
               }
               System.out.println("i= " + (i + 1));
           }
            System.out.println("测试输出");         // 输出不来是因为直接抛出了异常catch到了
        }catch (InterruptedException e){
            System.out.println("进入了catch中");
            e.printStackTrace();
        }
    }
}

总结:

interrupt设置标志位,在非阻塞状态下,将改为true,一旦进入阻塞状态,则会抛出异常,且中断标志清除

interrupted是静态方法,返回的是当前线程的中断状态,第一次调用返回true,然后清除标记,第二次就是false,当然,这期间没有抛出中断异常,否则中断异常就会被清除。

isInterrupted调用的话,一直会返回true,除非中断状态被清除了。



补充:java里的线程可以在阻塞的时候捕获中断异常并处理?(并没有在cpu上运行)


猜你喜欢

转载自blog.csdn.net/jae_wang/article/details/80087570