• Java多线程--基础(三)


    停止线程

    1. 使用退出标志,线程正常退出,也就是run方法完成后线程终止。
    2. 使用stop方法强行终止线程。(已经作废)
    3. 使用interrput()中断线程

    注意:interrupt()方法的使用效果并不像for+break语句那样,马上就停止循环。调用interrupt方法是在当前线程中打了一个停止标志,并不是真的停止线程。

    interrupted() 和 isInterrupter() 判断线程是否中断

    • interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能。
    • isInterrupted():测试线程Thread对象是否已经是中断状态,但是不清除状态位。

    异常法停止线程

    public class MyThread extends Thread {
        public void run(){
            super.run();
            for(int i=0; i<500000; i++){
                if(this.interrupted()) {
                    System.out.println("线程已经终止, for循环不再执行");
                    break;
                }
                System.out.println("i="+(i+1));
            }
            System.out.println("这是for循环外面的语句,也会被执行");
        }
    }
    
    public class Run {
        public static void main(String args[]){
            Thread thread = new MyThread();
            thread.start();
            try {
                Thread.sleep(2000);
                thread.interrupt();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    output:

    ...
    i=180136
    i=180137
    i=180138
    i=180139
    线程已经终止, for循环不再执行
    这是for循环外面的语句,也会被执行
    

    虽然停止了线程,但如果for语句下面还有语句,还是会继续运行的。

    public class MyThread extends Thread {
        public void run(){
            super.run();
            try {
                for(int i=0; i<500000; i++){
                    if(this.interrupted()) {
                        System.out.println("线程已经终止, for循环不再执行");
                            throw new InterruptedException();
                    }
                    System.out.println("i="+(i+1));
                }
    
                System.out.println("这是for循环外面的语句,也会被执行");
            } catch (InterruptedException e) {
                System.out.println("进入MyThread.java类中的catch了。。。");
                e.printStackTrace();
            }
        }
    }
    

    output:

    ...
    i=203798
    i=203799
    i=203800
    线程已经终止, for循环不再执行
    进入MyThread.java类中的catch了。。。
    java.lang.InterruptedException
        at thread.MyThread.run(MyThread.java:13)
    

    sleep()中停止线程

    public class MyThread extends Thread {
        public void run(){
            super.run();
    
            try {
                System.out.println("线程开始。。。");
                Thread.sleep(200000);
                System.out.println("线程结束。");
            } catch (InterruptedException e) {
                System.out.println("在沉睡中被停止, 进入catch, 调用isInterrupted()方法的结果是:" + this.isInterrupted());
                e.printStackTrace();
            }
    
        }
    }
    

    output:

    线程开始。。。
    在沉睡中被停止, 进入catch, 调用isInterrupted()方法的结果是:false
    java.lang.InterruptedException: sleep interrupted
        at java.lang.Thread.sleep(Native Method)
        at thread.MyThread.run(MyThread.java:12)
    

    如果在sleep状态下停止某一线程,会进入catch语句,并且清除停止状态值,使之变为false。

    废黜的stop()方法

    • 废除stop()方法的理由
    1. 强制停止线程可能使一些清理性的工作得不到完成。
    2. 会对锁定对象“解锁”导致数据不一致。

    使用return结合interrupt()停止线程

     public class MyThread extends Thread {
        public void run(){
            while (true){
                if(this.isInterrupted()){
                    System.out.println("线程被停止了!");
                    return;
                }
                System.out.println("Time: " + System.currentTimeMillis());
            }
        }
    }
    
    public class Run {
        public static void main(String args[]) throws InterruptedException {
            Thread thread = new MyThread();
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        }
    }
    

    output:

    ...
    Time: 1467072288503
    Time: 1467072288503
    Time: 1467072288503
    线程被停止了!
    

    建议使用“抛出异常”的方式来停止线程,因为在catch块中可以将异常上抛,使得线程停止的事件传播。

    暂停线程

    • suspend():暂停线程执行(已经作为)
    • resume():恢复线程执行(已经作废)
    1. 作废理由一 独占
      使用不当容易造成公共同步对象的独占,使得其他线程无法访问公共对象
    2. 作废理由二 不同步
      和stop方法类似,容易导致数据不同步

    yield()

    作用是放弃当前CPU资源,将它让给其他任务去占用CPU执行时间。但是放弃的时间不确定,可能刚刚放弃马上又获得CPU时间片。

    package ch01.test3;
    
    public class MyThread extends Thread {
        @Override
        public void run() {
            long beginTime = System.currentTimeMillis();
            int count = 0;
            for(int i = 0; i < 5000000; i++) {
                //Thread.yield();
                count = count + (i + 1);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("用时:"+ (endTime - beginTime) + "毫秒!");
        }
    }
    
    class Test {
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
            myThread.start();
        }
    }
    

    output:

    用时:4毫秒!
    

    去掉注释符号Thread.yield();后,输出为:

    用时:1753毫秒!
    

    作者:lykxbg —— 来一块小饼干

    出处:http://www.cnblogs.com/lykxbg/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Urlrewrite 配置信息写在另外的文件
    maven项目动态替换配置中的值
    搭建一个java博客
    那个不嫌弃你穷的姑娘,如果有一天真的离开了你,那只是因为,你把她弄哭了。
    常规工作流模型
    浅谈https(创建、传输、断开)
    日志相关杂
    主键生成
    自动化部署脚本(windows上传到linux)
    简述IO
  • 原文地址:https://www.cnblogs.com/lykxbg/p/13641448.html
Copyright © 2020-2023  润新知