在Java中有以下3种方法可以终止一个正在运行的线程:

    1、使用退出标志,是线程正常退出,也就是run方法完成后线程终止。

    2、使用stop方法强制终止线程,但不推荐使用这个方法,因为stop、suspend和resume一样,都是作废过期的方法。

    3、使用interrupt方法中断线程,大多数停止一个线程使用Thread.interrupt()方法,但是这个方法不会终止一个正在运行的线程,还需要加入一些判断才可以完成线程的停止。

 下面我就用几个例子来介绍一下各种停止线程的效果。

   一、停不了的线程——interrupt

     本例子将调用interrupt()方法来停止线程,但是效果并不理想,并不能停止正在运行的线程,因为调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不能真的停止线程。

public static void main(String[] args) {

    MyThread1 t = new MyThread1();

    t.start();

    try {

        Thread.sleep(2);                        t.interrupted();

    } catch (InterruptedException e) {

        System.out.println("main catch");

        e.printStackTrace();

    }

}

public static class MyThread1 extends Thread {

  
    @Override

    public void run() {

        super.run();

        for (int i = 0; i < 5000; i++) {

            System.out.println("i=" + (i + 1));

        }

    }

}

    运行结果我值截取了最后一段,控制台上正好输出到5000,说明调用interrupt方法并没有停止线程,运行结果如下:

java如何暂停主线程 java中如何停止一个线程_System

             

          那么怎么才能停止线程呢?下面我回来介绍。


二、能停止的线程——异常法

     先看一个例子:

public static void main(String[] args) throws InterruptedException {

  
    MyThread t = new MyThread();

    t.start();

    Thread.sleep(50);

    t.interrupt();

    System.out.println("end");

}

  
public static class MyThread extends Thread {

  
    @Override

    public void run() {

        // TODO Auto-generated method stub

        super.run();

        for (int i = 0; i < 5000; i++) {

            if (this.interrupted()) {

                System.out.println("已经是停止状态了!我要退出了!");

                break;

            }

  
            System.out.println("i=" + (i + 1));

        }

        System.out.println("如果我被输出了,说明run方法还在继续执行,线程并未停止!");

  
    }

}

      输出结果如下:

java如何暂停主线程 java中如何停止一个线程_停止线程_02

           


         从上面的结果可以看出来,这样写只是把for循环结束了,但是下面接着输出了“如果我被输出了,说明run方法还在继续执行,线程并未停止!”这句话,说明这样写并不能让run方法停止,所以这样写不可行。下面再来看一个例子。

public static void main(String[] args) throws InterruptedException {

  
    MyThread t = new MyThread();

    t.start();

    Thread.sleep(50);

    t.interrupt();

    System.out.println("end");

}

  
public static class MyThread extends Thread {

  
    @Override

    public void run() {

        super.run();

        try {

            for (int i = 0; i < 5000; i++) {

                if (this.interrupted()) {

                    System.out.println("已经是停止状态了!我要退出了!");                                                //异常法结束线程

                    throw new InterruptedException();

                }

                System.out.println("i=" + (i + 1));

            }

            System.out.println("我在for下面");

        } catch (InterruptedException e) {

            System.out.println("进入Thread线程的run方法中的catch!");

            e.printStackTrace();

        }

  
    }

}

     下面来看一下控制台上的输出结果:


         

java如何暂停主线程 java中如何停止一个线程_System_03


        来分析一下结果,throw new InterruptedException()这句话下面的内容已经不会再执行了,因为“我在for下面”这句话并没有输出来,而是进入了catch,结束了整个run方法。所以异常方法来停止线程方法是靠谱的。

三、在沉睡中停止线程

public static void main(String[] args) {

  
    try {

        MyThread t = new MyThread();

        t.start();

        Thread.sleep(200);

        t.interrupt();

    } catch (Exception e) {

        System.out.println("main catch");

        e.printStackTrace();

    }

    System.out.println("end!");

  
}

  
public static class MyThread extends Thread {

  
    @Override

    public void run() {

  
        super.run();

        try {

            System.out.println("run begin");                                //为了确保能停止线程,这个休眠时间尽量长一点,如果时间太短,有可能主线程还没休眠结束呢,子线程就休眠结束了,这个线程也就正常运行了。

            sleep(2000);

            System.out.println("run end");

        } catch (Exception e) {

            System.out.println("在沉睡中被停止!进去catch!" + this.isInterrupted());

            e.printStackTrace();

        }

    }

}

 


     运行结果如下:

           

java如何暂停主线程 java中如何停止一个线程_System_04


         来分析一下结果,"run end"这句话没有输出,说明子线程里的sleep下面的内容再也不会执行了,而是进入到catch里面了,从而停止了run方法。说明这样写也是靠谱的。


四、能停止的线程——暴力停止


 使用stop()方法停止线程是非常暴力的行为,并且使用stop()方法会导致运行结果不一样,已经被官方文档废弃使用了。不使用的原因是不安全,假如当执行到stop方法时,子线程正在执行 synchronized里边的内容,那么不管


synchronized的方法有没有执行完,都会立刻停止这个线程,造成线程不安全。下面我来展示一个例子。


public static void main(String[] args) {

  
    MyThread t = new MyThread();

    t.start();

    try {                       Thread.sleep(9000);

        t.stop();

    } catch (Exception e) {

  
        e.printStackTrace();

    }

}

  
public static class MyThread extends Thread {

  
    private int i = 0;

  
    @Override

    public void run() {

  
        super.run();

        while (true) {

            i++;

            System.out.println("i=" + i);

            try {

                sleep(1000);

            } catch (InterruptedException e) {

  
                e.printStackTrace();

            }

        }

    }

}

 


五、使用return停止线程

    将interrupt()和return结合也能实现停止线程的效果。但是建议使用抛异常停止线程,因为可以处理发生异常时候的相关信息。下面看一段代码。

public static void main(String[] args) throws InterruptedException {

  
    MyThread t = new MyThread();

    t.start();

    Thread.sleep(2);

    t.interrupt();

  
}

  
public static class MyThread extends Thread {

  
    @Override

    public void run() {

  
        super.run();

  
        for (int i = 0; i < 5000; i++) {

            if (this.interrupted()) {

                System.out.println("已经是停止状态了!我要退出了!");

                return;

            }

            System.out.println("i=" + (i + 1));

        }

  
    }

}

     下面看一下运行结果:

java如何暂停主线程 java中如何停止一个线程_停止线程_05

           


六、暂停线程

     暂停线程异味着此线程还可以恢复运行,在java中使用suspend()方法暂停线程,使用resume()方法恢复线程。不推荐suspend()和resume()方法,是因为容易造成死锁,比如执行suspend()这个方法的线程持有一个重要资源的锁,那么在没有执行恢复方法之前,是不会释放掉这个锁的,但是这个时候有另一个线程执行了resume()方法,但是这个线程恢复以后要想继续执行下去需要那个重要资源的锁,这个时候两个线程就造成死锁了

使用下面看一段代码。

public static void main(String[] args) throws InterruptedException {

  
    MyThread t = new MyThread();

    t.start();

    //A段    暂停线程

    t.suspend();

    System.out.println("A="+System.currentTimeMillis() +"\t"+"i="+t.getI());

    Thread.sleep(500);

    System.out.println("A="+System.currentTimeMillis() +"\t"+"i="+t.getI());

    //B段    继续恢复

    t.resume();

    System.out.println("B="+System.currentTimeMillis() +"\t"+"i="+t.getI());

    Thread.sleep(500);

    System.out.println("B="+System.currentTimeMillis() +"\t"+"i="+t.getI());

    //C段    暂停线程

    t.suspend();

    System.out.println("C="+System.currentTimeMillis() +"\t"+"i="+t.getI());

    Thread.sleep(500);

    System.out.println("C="+System.currentTimeMillis() + "\t"+"i="+t.getI());

}

  
public static class MyThread extends Thread {

  
    private long i = 0;

    public long getI(){

        return i;

    }

    public void setI(long i){

        this.i=i;

    }

    @Override

    public void run() {

      
        super.run();

        while (true) {

            i++;

        }

    }

}

 下面来分析一下运行结果:在A段中,先执行的是suspend()暂停线程的方法,所以从结果可以看出,系统的当前时间在变,但是i值确一直是0,说明线程没有在执行,仍是初始化的值,到了B段,执行了resume()恢复线程的方法,从结果也可以看出,当前系统的时间在变,i值也在改变,说面线程已经被恢复并在执行了,到了C段,出现这样的结果和A段原因是一样的。

     

java如何暂停主线程 java中如何停止一个线程_停止线程_06


以上我说了很多小例子,如果亲手敲一遍代码,看一下执行结果,会有更好的理解,毕竟线程执行的结果不是单一的。