zoukankan      html  css  js  c++  java
  • interrupted()和isInterrupted()比较+终止线程的正确方法+暂停线程

    interrupted():测试当前线程【运行此方法的当前线程】是否已经是中断状态,执行后具有将状态标志清除为false的功能。

    isInterrupted():测试线程对象是否已经是中断状态,但不清除状态标志。

    interrupted()的例子:

    public static void main(String[] args) {
        try{
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(1000);
            thread.interrupt();
            syso(thread.interrupted());
            syso(thread.interrupted());
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
    //运行结果
    false
    false

    从上可以看出thread.interrupted()执行的是运行当前方法的线程,而不是thread线程,而由于main线程一直没有停止,所以一直是false。

    public static void main(String[] args) {
        Thread.currentThread().interrupt();
        syso(Thread.interrupted());
        syso(Thread.interrupted());
    }
    //运行结果
    true
    false

    从上可以看出Thread.currentTrhead().interrupt()将main线程停止了,所以下面第一个是true状态,而第二个是false状态,就是因为interrupted()方法有清空状态标志的功能。

    isInterrupted()的例子:

    public static void main(String[] args) {
        try{
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(1000);
            thread.interrupt();
            syso(thread.isInterrupted());
            syso(thread.isInterrupted());
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
    //运行结果
    true
    true

    从上面可以看出isInterrupted()就是线程对象是否中断。

    interrupt()并不能真正的结束线程:

    public class MyThread extends Thread{
        public void run() {
            super.run();
            for(int i = 0; i < 5; i++) {
                if(this.interrupted()) {
                    System.out.println("已经是停止状态了!我要退出了!");
                    break;
                }
                System.out.println("i = " + i);
            }
            System.out.println("for之后代码");
        }
    }
    public class Main {
    
        public static void main(String[] args) {
            try {
                MyThread thread = new MyThread();
                thread.start();
                Thread.sleep(2000);
                thread.interrupt();
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("结束了");
        }
    
    }

    运行结果:

    可以发现interrupt()并没有真正终止线程。下面介绍几种可以终止线程的方法:

    1.异常法【建议使用】:

    if(this.interrupted()) {
                    System.out.println("已经是停止状态了!我要退出了!");
        throw new InterruptedException();
                    break;
                }

    在上面需要正常终止的地方抛出异常即可。

    此方法最推荐使用,因为在catch块中还可以将异常向上抛,使线程停止的事件得以传播。

    2.在sleep中interrupt():

    public class SleepThread extends Thread{
        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("沉睡中停止,进入catch");
                e.printStackTrace();
            }
        }
    }
    public class SleepMain {
    
        public static void main(String[] args) {
            try {
                SleepThread thread = new SleepThread();
                thread.start();
                Thread.sleep(200);
                thread.interrupt();
            } catch(InterruptedException e) {
                System.out.println("main catch");
                e.printStackTrace();
            }
            System.out.println("结束了");
        }
    
    }

    运行结果:

    3.使用作废的stop()方法:

    调用stop()方法会强制让线程停止则有可能使一些清理性的工作得不到完成。并且有可能对锁定对象进行了“解锁”,导致数据得不到同步处理,出现数据不一致问题。

    4.return法:

    public class ReturnThread extends Thread{
        public void run() {
            while(true) {
                if(this.isInterrupted()) {
                    System.out.println("停止了!");
                    return;
                }
                System.out.println("timer" + System.currentTimeMillis());
            }
        }
    }
    public class ReturnMain {
    
        public static void main(String[] args) throws InterruptedException {
            ReturnThread thread = new ReturnThread();
            thread.start();
            Thread.sleep(20);
            thread.interrupt();
        }
    
    }

    在需要停止的地方return即可。

     暂停线程所使用的suspend()和resume()已经弃用,这里看一下suspend()方法:

    当某个线程的suspend()方法被调用时,该线程会被挂起。如果该线程占有了锁,则它不会释放锁。即,线程在挂起的状态下还持有锁。

    public class MyThread extends Thread{
        private long i = 0;
        public void run() {
            while(true) {
                i++;
                //syso是一个同步方法
                System.out.println(i);
            }
        }
    }
    public class Main {
    
        public static void main(String[] args) {
            try {
                MyThread thread = new MyThread();
                thread.start();//启动一个线程'thread'
                Thread.sleep(1000);//使当前线程(main线程)睡眠
                thread.suspend();//挂起线程'thread'
                //下面这一行不会执行,因为println一直被占用
                System.out.println("main end!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

    下面看一下println()源码:

        public void println(long x) {
            synchronized (this) {
                print(x);
                newLine();
            }
        }

    从上可以看出suspend()暂停线程之后不会释放锁。

    而在main中调用resume(),可以恢复线程,线程执行完毕就会释放锁。

  • 相关阅读:
    如果 BitTorrent 协议内置代币会如何?
    为什么 ETH2.0 要选择 libp2p ?
    关于 PoW 和 PoS
    Ceph 分布式存储架构解析与工作原理
    云端之战:Google Cloud 的多云战略和甲骨文的数据库云
    迈向全球经济结算层
    Hydro:DeFi 作为去中心化交易协议的依归
    Echo | 多副本共享账本的意义
    时间1234567890
    时间1234567890
  • 原文地址:https://www.cnblogs.com/cing/p/8997582.html
Copyright © 2011-2022 走看看