java,go 停止线程

如何停止线程?

参考:https://www.zhihu.com/question/41048032

 

一、java

1.禁止使用stop方法

java 禁止使用Thread.stop方法

2.使用interrupt方法

首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。

而 Thread.interrupt的作用其实也不是中断线程,而是「通知线程应该中断了」,
具体到底中断还是继续运行,应该由被通知的线程自己处理。

具体来说,当对一个线程,调用interrupt方法时:

(1)线程处于被阻塞状态

如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常,仅此而已。不像stop,interrupt方法会继续执行下面的代码。

testInterrupt.java

其中的thread1在处于阻塞状态时被interrupt中断,抛出InterruptedException错误,马上继续执行了下面的syso。而thread2在进入阻塞状态3秒之后才结束。

(2)线程处于运行状态

如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响(只是提供给运行中的线程一个中断的信息而已,提醒线程自己结束任务,而不是像stop方法一样强制结束线程)。

testInterrupt.java

在线程正常执行for循环的时候,就尝试使用interrupt方法将其中断。结果为:

可以看到isInterrupted方法为true。也就是说,我们可以在线程中加入判断,起到线程自己停止的效果。

(3)加入判断使线程自己停止

加入一个while循环,如果线程没有被interrupt,那就继续运行。

这里的thread1永远不会进入到阻塞状态,肯定会一直运行。interrupt之后while循环就无法继续执行了。当然这里我们知道thread1永远不会被阻塞,所以才能这样写。但是如果我们知道thread1肯定会被阻塞,要怎么写呢(在这里要知道java线程在什么时候会被阻塞,这里不涉及)?

如果我们希望线程一被阻塞就马上停止,可以这样写:


在这里我使用sleep方法主动阻塞了线程。一旦thread1使用了interrupt方法,线程中就会catch到错误,直接return。同时finally可以做一些回收工作。线程一旦被阻塞就马上退出,我现在还没有想到应用场景…

二、Go

现在想来,go中的channel是不是和java中的interrupt方法有点像呢?之前我们是这样使用channel的:

这里的channel,从子线程(goroutine)告诉主线程,我工作完了,现在可以继续下一步了。既然是channel,那么同样的,应该可以从主线程告诉子线程,你可以停止了。这样是不是和java中interrupt的思想很像?都是告诉子线程可以停止了,而不是强制关闭子线程。只不过go中没有isinterrupted这个状态而已。

改写一下这个例子:

在这里,我们新定义了一个名为interrupt的channel:

在主线程中初始化了这个名为interrupt的channel:

然后往interrupt中输入一个bool信号,告诉子线程你应该关闭了:

子线程中收到了这个信号:

如果不需要要停止,那么就执行逻辑:

执行完后,往channel中输入一个结束的信号,告诉主线程,子线程已经执行完毕了,可以继续执行下面的代码。

三、总结

回顾了一下如何中断线程,为什么要这样中断,感觉对多线程有了更深的了解。尤其是go中channel的用法很巧妙,要好好学习这种设计思想。

发表评论

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