当前位置 主页 > 网站技术 > 代码类 >

    面试题:Java中如何停止线程的方法(2)

    栏目:代码类 时间:2019-09-11 18:03

    第二个例子:在子方法中捕获中断异常,但是捕获以后当前线程的中断控制位将被清除,父方法执行时将无法感知中断。所以此时在子方法中重新设置中断,这样父方法就可以通过对中断控制位的判断来处理中断:

    public class Demo5 implements Runnable{  @Override  public void run() {    while(true && !Thread.currentThread().isInterrupted()){//每次循环判断中断控制位      System.out.println("go");      throwInterrupt();    }    System.out.println("检测到了中断,循环打印退出");  }  private void throwInterrupt(){    try {      Thread.sleep(2000);    } catch (InterruptedException e) {      Thread.currentThread().interrupt();//重新设置中断      e.printStackTrace();    }  }  public static void main(String[] args) throws InterruptedException {    Thread thread = new Thread(new Demo5());    thread.start();    Thread.sleep(1000);    thread.interrupt();  }}

    讲到这里,正确的停止线程方法已经讲的差不多了,下面我们看一下常见的错误停止线程的例子:

    3. 常见错误停止线程例子:

    这里介绍两种常见的错误,先说比较好理解的一种,也就是开头所说的,在外部直接把运行中的线程停止掉。这种暴力的方法很有可能造成脏数据。

    看下面的例子:

    public class Demo6 implements Runnable{  /**   * 模拟指挥军队,以一个连队为单位领取武器,一共有5个连队,一个连队10个人   */  @Override  public void run() {    for(int i = 0; i < 5; i++){      System.out.println("第" + (i + 1) + "个连队开始领取武器");      for(int j = 0; j < 10; j++){        System.out.println("第" + (j + 1) + "个士兵领取武器");        try {          Thread.sleep(100);        } catch (InterruptedException e) {          e.printStackTrace();        }      }      System.out.println("第" + (i + 1) + "个连队领取武器完毕");    }  }  public static void main(String[] args) throws InterruptedException {    Thread thread = new Thread(new Demo6());    thread.start();    Thread.sleep(2500);    thread.stop();  }}

    在上面的例子中,我们模拟军队发放武器,规定一个连为一个单位,每个连有10个人。当我们直接从外部通过stop方法停止武器发放后。很有可能某个连队正处于发放武器的过程中,导致部分士兵没有领到武器。

    这就好比在生产环境中,银行以10笔转账为一个单位进行转账,如果线程在转账的中途被突然停止,那么很可能会造成脏数据。

    另外一个“常见”错误可能知名度不是太高,就是:通过volatile关键字停止线程。具体来说就是通过volatile关键字定义一个变量,通过判断变量来停止线程。这个方法表面上是没问题的,我们先看这个表面的例子:

    public class Demo7 implements Runnable {  private static volatile boolean canceled = false;  @Override  public void run() {    int num = 0;    while(num <= Integer.MAX_VALUE / 2 && !canceled){      if(num % 100 == 0){        System.out.println(num + "是100的倍数");      }      num++;    }    System.out.println("退出");  }  public static void main(String[] args) throws InterruptedException {    Thread thread = new Thread(new Demo7());    thread.start();    Thread.sleep(1000);    canceled = true;  }}

    但是这个方法有一个潜在的大漏洞,就是若线程进入了阻塞状态,我们将不能通过修改volatile变量来停止线程,看下面的生产者消费者例子: