怎么在java中关闭一个thread

我们经常需要在java中用到thread,我们知道thread有一个start()方法可以开启一个线程。那么怎么关闭这个线程呢?

有人会说可以用Thread.stop()方法。但是这个方法已经被废弃了。

根据Oracle的官方文档,Thread.stop是不安全的。因为调用stop方法的时候,将会释放它获取的所有监视器锁(通过传递ThreadDeath异常实现)。如果有资源该监视器锁所保护的话,就可能会出现数据不一致的异常。并且这种异常很难被发现。 所以现在已经不推荐是用Thread.stop方法了。

那我们还有两种方式来关闭一个Thread。

  1. Flag变量

如果我们有一个无法自动停止的Thread,我们可以创建一个条件变量,通过不断判断该变量的值,来决定是否结束该线程的运行。

public class KillThread implements Runnable {
private Thread worker;
private final AtomicBoolean running = new AtomicBoolean(false);
private int interval; public KillThread(int sleepInterval) {
interval = sleepInterval;
} public void start() {
worker = new Thread(this);
worker.start();
} public void stop() {
running.set(false);
} public void run() {
running.set(true);
while (running.get()) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
log.info("Thread was interrupted, Failed to complete operation");
}
// do something here
}
log.info("finished");
} public static void main(String[] args) {
KillThread killThread= new KillThread(1000);
killThread.start();
killThread.stop();
} }

上面的例子中,我们通过定义一个AtomicBoolean 的原子变量来存储Flag标志。

我们将会在后面的文章中详细的讲解原子变量。

  1. 调用interrupt()方法

通过调用interrupt()方法,将会中断正在等待的线程,并抛出InterruptedException异常。

根据Oracle的说明,如果你想自己处理这个异常的话,需要reasserts出去,注意,这里是reasserts而不是rethrows,因为有些情况下,无法rethrow这个异常,我们需要这样做:

 Thread.currentThread().interrupt();

这将会reasserts InterruptedException异常。

看下我们第二种方法怎么调用:

public class KillThread implements Runnable {
private Thread worker;
private final AtomicBoolean running = new AtomicBoolean(false);
private int interval; public KillThread(int sleepInterval) {
interval = sleepInterval;
} public void start() {
worker = new Thread(this);
worker.start();
} public void interrupt() {
running.set(false);
worker.interrupt();
} public void stop() {
running.set(false);
} public void run() {
running.set(true);
while (running.get()) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
log.info("Thread was interrupted, Failed to complete operation");
}
// do something here
}
log.info("finished");
} public static void main(String[] args) {
KillThread killThread= new KillThread(1000);
killThread.start();
killThread.interrupt();
}
}

上面的例子中,当线程在Sleep中时,调用了interrupt方法,sleep会退出,并且抛出InterruptedException异常。

本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/kill-thread

更多教程请参考 flydean的博客

怎么在java中关闭一个thread的更多相关文章

  1. java中的daemon thread

    java中的daemon thread java中有两种类型的thread,user threads 和 daemon threads. User threads是高优先级的thread,JVM将会等 ...

  2. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

  3. 应用于Java中的一个开源的表达式语言(Expression Language)

    OGNL(英文全称:Object Graph Navigation Language,中文名:对象导航图语言)是应用于Java中的一个开源的表达式语言(Expression Language),它被集 ...

  4. Java中传入一个时间范围,取出该时间范围内所有日期的集合

    直接上代码: import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; impor ...

  5. 怎么在java中创建一个自定义的collector

    目录 简介 Collector介绍 自定义Collector 总结 怎么在java中创建一个自定义的collector 简介 在之前的java collectors文章里面,我们讲到了stream的c ...

  6. Java中Runnable和Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...

  7. Java中的线程Thread总结

    首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的! 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口. 要注意的是Threa ...

  8. Java中的线程Thread方法之---interrupt()

    前几篇都介绍了Thread中的几个方法,相信大家都发现一个相似点,那就是sleep,join,wait这样的阻塞方法都必须捕获一个InterruptedException异常,顾名思义就是一个线程中断 ...

  9. Java中的线程Thread方法之---stop()

    搞过Java线程的人都知道,stop这个方法是臭名昭著了,早就被弃用了,但是现在任然有很多钟情与他的人,永远都放不下他,因为从他的字面意思上我们可以知道他貌似可以停止一个线程,这个需求是每个搞线程开发 ...

随机推荐

  1. Activiti网关--并行网关

    1.什么是并行网关 并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进 入和外出顺序流的: fork 分支: 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支. ...

  2. JVM系列十(虚拟机性能监控神器 - BTrace).

    BTrace 是什么? BTrace 是一个动态安全的 Java 追踪工具,它通过向运行中的 Java 程序植入字节码文件,来对运行中的 Java 程序热更新,方便的获取程序运行时的数据信息,并且,保 ...

  3. Altium 分形天线设计

    Altium 分形天线设计 程序运行界面 Cantor三分集 Koch雪花 Sierpinski垫片 源代码: Iter_Num = 4     'diedai PI = 3.1415926 Call ...

  4. java web数据库的增删改查详细

    本次课上实验是完成数据库的增删改查. 包括增加用户信息.删除用户信息.多条件查找用户信息.修改用户信息(主要是复选框单选框等的相关操作.) 下面下看一下各个界面的样子. 总页面:显示全部页面:增加页面 ...

  5. 2018蓝桥杯省赛(C/C++ C组)

    因进考场不让带优盘,顾想不起有些啥题了,静待更新吧! 再次强调C++最新标准,main函数必须指定返回类型为int,且返回值最好为0(人走的多了就是路了,有人偏返回999那也没办法) 1.大概是小明给 ...

  6. javascript入门 之 zTree(十四 增删查改)(一)

    <!DOCTYPE html> <HTML> <HEAD> <TITLE> ZTREE DEMO - beforeEditName / beforeRe ...

  7. mysql全文索引浅谈

    原文链接:http://www.cnblogs.com/robertsun/p/5999588.html 对于一些简单的检索可以通过mysql自带的全文索引及 MATCH AGAINST 查询语句实现 ...

  8. 10.6 IoStudentManager

    package day11_io_student.student_demo; public class Student { private String id; private String name ...

  9. 游戏开服 报一些 ip 设置 数据格式的异常,但断点明明都是数字 没问题的

    游戏服开始起服,结果报乱七八招的错误,先  ccs 那 ip 有问题,我给直接注释掉了:然后又 报 KeyValueDictCache 中 ips 设置有问题,都是报格式错误,结果我断点明明都是数字结 ...

  10. shell 数组遍历加引号和不加引号的区别?

    前言 shell 是一个比较神奇的国度,里面有太多的坑需要填,今天需要填的坑就是,数组遍历在使用时加了引号和不加引号的区别. 案例 解析: 不加引号,数组中元素间的“空格”就会编程换行符 加引号,  ...