如何优雅去的去终止一个线程,这也是使用多线程应该考虑的问题

这个优雅就是让一个线程接手到了终止指令,让其可以料理完后事,安稳的被终止掉了

那么,可以采用两阶段终止模式,就是将终止过程分别为了两个过程,一阶段就是T1向T2发送终止指令,二阶段用于响应终止指令,即真正的终止线程的运行

在Java的Thread使用过程中,终止的方式之前也说过,可以通过stop()或者interrupt()方法,但是stop()太过于粗暴了,不适合直接的使用,

那么我们使用interrupt()方法,在使用的时候,需要注意一点,就是线程所处于的状态,

线程可以从Runnable状态转换为终止状态,但是在线程的生命周期中,除了运行状态还有休眠状态

图片

那么interrupt()方法,会先设置一个标志位,然后来进行唤醒线程

线程检查符合标志位了,进行退出run()方法,响应终止指令

那么可以简单的总结为,

1.使用interrupt()方法去唤醒线程

2.线程检测标志位去终止

我们用一个简单的代码去实现终止操作

下面就是使用了start()方法去启动线程,然后使用stop去终止线程

class Proxy {

boolean started = false;

//采集线程

Thread rptThread;

//启动采集功能

synchronized void start(){

//不允许同时启动多个采集线程

if (started) {

return;

}

started = true;

rptThread = new Thread(()->{

while (!Thread.currentThread().isInterrupted()){

//省略采集、回传实现

report();

//每隔两秒钟采集、回传一次数据

try {

Thread.sleep(2000);

} catch (InterruptedException e){

//重新设置线程中断状态

Thread.currentThread().interrupt();

}

}

//执行到此处说明线程马上终止

started = false;

});

rptThread.start();

}

//终止采集功能

synchronized void stop(){

rptThread.interrupt();

}

}

上述代码,就是利用一个interrupt()唤醒了等待线程,并抛出了InterruptedException异常,然后捕捉到了异常,说明是运行中了,由于异常捕获机制,会清除了中断异常,需要我们重新设置了中断状态,进行终止

但是在实际生活中,需要谨慎的使用,因为有些第三方的类库不会抛出中断异常,或者捕获到Interrupted异常不会设置中断状态

导致不会正常终止,所以最好还是自己设置一个线程终止的标志位,使用isDown作为一个标志位,只要终止,就将其设置为改变

class Proxy {

//线程终止标志位

volatile boolean terminated = false;

boolean started = false;

//采集线程

Thread rptThread;

//启动采集功能

synchronized void start(){

//不允许同时启动多个采集线程

if (started) {

return;

}

started = true;

terminated = false;

rptThread = new Thread(()->{

while (!terminated){

//省略采集、回传实现

report();

//每隔两秒钟采集、回传一次数据

try {

Thread.sleep(2000);

} catch (InterruptedException e){

//重新设置线程中断状态

Thread.currentThread().interrupt();

}

}

//执行到此处说明线程马上终止

started = false;

});

rptThread.start();

}

//终止采集功能

synchronized void stop(){

//设置中断标志位

terminated = true;

//中断线程rptThread

rptThread.interrupt();

}

}

增加了一个标志位,将线程终止了

那么关于单一线程之后,关于线程池如何进行终止,常见提供的方法为,shutdown(),shutdownNow() 两个方法有什么区别

shutDown()方式是一个保守的方法,就是接收到showdown()方法之后,拒绝新的任务,等待线程池所有任务(包括阻塞队列的任务)完成后关闭线程池

shutdownNow()方法相对激进了,就是接收到了shoudownNow()方法之后,就会中断所有正在执行的代码,而且清空阻塞队列,不过可以将剥夺了执行权的任务作为返回值进行返回,比较暴力,不推荐使用

如果线程支持后续以补偿的方式重新执行,倒是可以使用shutdownNow()方法去执行

发表评论

邮箱地址不会被公开。 必填项已用*标注