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毫秒!
posted @ 2020-09-09 20:17  来一块小饼干  阅读(82)  评论(0编辑  收藏  举报