终止线程

       我们知道,我们可以通过线程的start方法启动一个新的线程,很多时候我们选择在线程的run方法中使用while循环,这样的话就导致线程一直运行,如果我们需要终止线程时应该怎么做呢?

       必须注意到,在Thread类中有一个Thread.stop() 方法,但是是被标记为deprecated,也就是不建议使用了。不建议使用的主要原因是stop方法会导致线程进入一个不安全状态,所以我们不能通过调用stop() 方法来终止线程。那我们还有其他的方法么?答案是肯定的。

      我们知道,一个线程的运行逻辑集中在run方法之中,当run方法执行结束,我们的线程也就终止了,所以我们可以通过一些措施来提前结束run方法以达到终止线程的目的。

1) 使用一个状态变量

       这个方法的思想就是在每次循环开始之前检查状态变量,如果被标记为需要终止,那么循环直接结束。

    主要代码如下:

     

private volatile boolean stop = false;
public void run()
{
      while(!stop)
       {
             doSomething();
        }
}

public void stopThread()
{
    this.stop = true;
}


至于为什么要使用volatile,主要是为了线程安全,防止在多线程环境下出现不一致的情况,其实这也是volatile关键字常见的使用场所。

这种方法简单,容易理解,但是也存在一些问题,比如上面的程序,假如线程阻塞在doSomething() 方法上,则我们终止线程的目的就打不到了。

2)  使用Thread.interrupt()

      当调用interrupt方法时,如果线程正处于blocked状态,比如正在sleep或者wait时,线程就会触发InterrutedException,程序进入异常处理模块,根据具体的情形可以终止线程。如下所示

Runnable r = new Runnable() 
{
  public void run() 
  {
    try 
    {
      while (true)
      {
        Thread.sleep(1000L);
        ...
      }
    } 
    catch (InterruptedException ex)
    {
      System.err.println("The thread interrupted");
    }
  }
};
Thread th = new Thread(r);
th.start();
当其他线程调用th.interrupt()方法时,线程th就会输出错误信息后结束。

上面的程序很好理解,但是如果在run函数中没有阻塞的方法调用时应该怎么办呢?如果没有阻塞的方法,则调用th.interrupt()时不会触发异常处理模块,也就不会终止线程了。这个时候就需要我们手动检查线程的状态了,首先我们知道,当对th调用interrupt方法时,系统将会对th设置一个中断标记(Interrupted Flag),其次我们可以通过使用isInterrupted方法判断标记值。有了上面两个信息,我们就可以通过手动判断中断标记位的值来判断是否需要中断了。

public void performLongCalculation() throws InterruptedException
{
  for (int i = 0; i < PART_COUNT; i++) 
  {
    if (isInterrupted())
        throw new InterruptedException();
    performPartOfCalculation();
  }
}

上面的程序在每次计算之前先检查标记位,如果其他线程触发了中断,则直接抛出中断异常。上层调用者就可以捕获这个异常并作相应的处理。

但是这时需要注意一点:当中断异常被捕获以后,终端标记位的值会被清空,所以有时为了能够让上上层调用者也发现这个异常,一般需要重新抛出一个中断异常。

Thread.currentThread.interrupt();


3) 其他方式

    假设一个场景:对于一个基于客户端/服务端的聊天系统来说,每个客户端有一个线程与服务器端进行通信,这时服务器端需要重启,那么如何才能优雅的关闭客户端到服务器端的连接呢?是不是只需要向客户端发送一个消息,消息内容告诉客户端,我将要重启,请关闭你到我的连接?所以这也算是一个终止线程的方法,通过消息机制,将终止线程的请求封装到一个消息中。

    上面三种方法各有自己的优缺点,需要我们根据具体的业务需求选择合适的方法。如果各位认为上面内容有误或者还有其他的思路,请留言!谢谢!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值