【Java 多线程】Java 如何停止线程

总结如下几种方式使线程停止执行:
(1)共享bool类型变量方式;
(2)调用线程interrupt方式,同时通过isInterrupted方式判断线程是否被停止,若停止则终止循环操作(线程类中循环外没有其他操作);
(3)调用线程interrupt方式 + 抛出异常方式(循环外有其他操作情况);
(4)调用线程interrupt方式 + return方式(循环外有其他操作情况);
(5)将线程设置为守护线程,则所有非守护线程停止时,守护线程便结束;
下面对以上五种方式分别进行详细解释。

方法一:采用bool类型共享变量的方式
子线程与主线程共享一个实例对象,该对象中包含一个bool类型变量,可以在主线程中对该bool类型变量进行赋值,从而在子线程循环中通过判断该值确定是否继续;

注意:当有多个线程共享该变量时,考虑是否采用volatile关键字修饰该变量,保证所有线程读取到的变量为最新值;
参考代码如下:

package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class MyObject {
    volatile public boolean flag = true;
}
package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class ThreadTest implements Runnable{

    MyObject myObject = null;

    public ThreadTest(MyObject myObject){
        this.myObject = myObject;
    }

    @Override
    public void run() {

        while (myObject.flag){

        }
        System.out.println(Thread.currentThread().getId() + " 线程退出!");
    }
}

package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class Main {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();

        new Thread(new ThreadTest(myObject)).start();
        try {
            Thread.sleep(1000);
            myObject.flag = false;//停止线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class Main {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();

        new Thread(new ThreadTest(myObject)).start();
        try {
            Thread.sleep(1000);
            myObject.flag = false;//停止线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

最后运行结果为:
这里写图片描述

方法二:调用线程interrupt方式,同时通过isInterrupted方式判断线程是否被停止
与方法一类似,当线程循环外无其他语句时,外部调用该线程的interrupt方法,线程内部通过判断isInterrupted方式判断线程是否被停止从而终止循环;
参考代码如下:

package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class ThreadTest extends Thread{



    @Override
    public void run() {

        while (!this.isInterrupted()){

        }
        System.out.println(Thread.currentThread().getId() + " 线程退出!");
    }
}

package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class Main {
    public static void main(String[] args) {

        Thread thread = new ThreadTest();
        thread.start();
        try {
            Thread.sleep(1000);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果为:

这里写图片描述
方法三:当线程内部循环外仍有其他语句时,采用上述两种方法只能退出循环,而不能阻止循环外的语句执行。此时我们可以采取抛出异常的方式。当线程通过isInterrupted函数判断线程已被停止后,可以抛出异常InterruptedException来终止整个线程的执行。
参考代码如下:

package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class ThreadTest extends Thread{

    @Override
    public void run() {
        try {
            int i = 5000000;
            while (i>0){
                System.out.println(i);
                if (this.isInterrupted()){
                    System.out.println(Thread.currentThread().getId() + " 线程退出!");
                    throw new InterruptedException();
                }
                i--;
            }
            System.out.println(Thread.currentThread().getId() + " 线程继续执行");

        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println(Thread.currentThread().getId() + " 抛出异常,进入catch代码块");
        }

    }
}
package study20170304;

/**
 * Created by apple on 17/3/4.
 */
public class Main {
    public static void main(String[] args) {

        Thread thread = new ThreadTest();
        thread.start();
        try {
            Thread.sleep(1000);
            thread.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

此时程序运行结果为:
这里写图片描述

方法四:与方法三相同,只不过可以不抛出异常,而是直接return;但是《Java多线程编程核心技术》一书中写道:不过还是建议使用“抛异常”法来实现线程的停止,因为在catch块中可以对异常的信息进行相关的处理,而且实用异常流能更好、更方便的控制程序的运行流程,不至于代码中出现很多个return;造成污染。

方法五:将一个线程设置为守护线程后,当进程中没有非守护线程后,守护线程自动结束;
如下代码,在main函数中将ThreadTest线程设置为守护线程,则main函数所在主线程执行完毕后,守护线程也结束;
参考代码如下:

package study20170304;
/**
 * Created by apple on 17/3/4.
 */
public class Main {
    public static void main(String[] args) {

        Thread thread = new ThreadTest();
        thread.setDaemon(true);
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值