JAVA线程终止方式的思考

在java的线程中提供了stop这个方法来终止线程的执行,但是使用这种方式来终止线程的执行时非常危险的,这样子会破坏线程执行的原子性,导致数据丢失或者其他什么更为严重的问题。所以,在java的规范中不建议使用这种方法来终止线程的执行。那么,既然这种方法是不建议使用的,而我们在实际的项目开发过程中是需要对线程进行中断的,那我们该怎么办呢?
解决的方式就是采用一个标志位的方法来控制,线程轮询这个标志位,当发现这个标志位发生改变的时候,线程进行终止,这样比较安全一些。代码如下:

    package thread;

import java.util.concurrent.TimeUnit;

public class StopThread {
    private static boolean stop = false;

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                int i = 0;
                while (stop == false) {
                    System.out.print(i + "\t");
                    i++;

                }

            }

        });

        thread.start();
        TimeUnit.SECONDS.sleep(1);
        stop = true;

    }

}

但这种方式在有的情况下会一直执行下去,并不会像我们所预期的那样正常的终止线程的执行,问题在于,没有使用同步,就不能保证后台的线程什么时候看到标志位所做的改变。
要解决这个问题,我们只能写一个同步的方法,轮询这个标志位,代码如下:

package thread;

import java.util.concurrent.TimeUnit;

public class StopThread2 implements Runnable{

    private boolean is = false;
    private int i = 0;
    public synchronized boolean isStop(){
        return is;
    }

    public synchronized void setIs(boolean is){
        this.is = is;
    }

    @Override
    public void run() {
        while(!isStop()){
            System.out.println(i);
            i++;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        StopThread2 th2 = new StopThread2();
        Thread thread = new Thread(th2);
        thread.start();  //线程启动
        TimeUnit.SECONDS.sleep(1);
        th2.setIs(true);
    }



}

在isStop()方法中的操作,即使没有同步,也是原子性的,这些方法只是为了他们的通信效果,并不是为了变量的互斥访问。虽然循环迭代的开销很小,但是我们还有一种更为简洁和更为高效的方法,那就是使用volatile来修饰。
我们都知道,编译器为了使我们的代码执行的效率更高,对于变量,它使用了一种缓存机制。在多线程中,变量被多个线程访问的时候,被修改的值常常来不及放入到缓存中,就被其他的线程所访问,这容易造成不一致的问题,使用volatile就可以很好的来解决这个问题。使用volatile修饰的变量是不进行缓存的,使得线程可以迅速的看到其他线程对这个值所作出的修改。结合我们现在的场景进行分析,我们发现,我们在这里可以使用这个关键字对我们的代码进行优化处理。修改后的代码如下:

package thread;

import java.util.concurrent.TimeUnit;

public class StopThread2 implements Runnable{

    private volatile boolean is = false;
    private int i = 0;


    @Override
    public void run() {
        while(!is){
            System.out.println(i);
            i++;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        StopThread2 th2 = new StopThread2();
        Thread thread = new Thread(th2);
        thread.start();  //线程启动
        TimeUnit.SECONDS.sleep(1);
        th2.is = true;
    }



}

转载于:https://my.oschina.net/zhanghongbin01/blog/547731

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值