当前位置:   article > 正文

java 多线程编程系列之5----如何优雅的结束线程_如何优雅控制异步多线程的结束

如何优雅控制异步多线程的结束

        线程的结束方式一stop:

        stop()会释放所有的锁,并且不会做善后工作,会导致其他线程抢到锁,然后读取到中间数据导致数据不一致;所以stop方法废弃了;

  1. public class TestThread {
  2. @SneakyThrows
  3. public static void main(String[] s){
  4. Thread t1 = new Thread(()->{
  5. while (true){
  6. try {
  7. System.out.println("go on ...");
  8. TimeUnit.SECONDS.sleep(1);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. });
  14. t1.start();
  15. TimeUnit.SECONDS.sleep(5);
  16. t1.stop();
  17. }
  18. }

        线程的暂停/继续:

        暂停的时候是不会释放当前线程所拥有的锁的,假如你没有继续启动resume的话就会导致死锁,所以这两个方法suspend()和resume()废弃了,最好别轻易使用。

  1. public class TestThread {
  2. @SneakyThrows
  3. public static void main(String[] s){
  4. Thread t1 = new Thread(()->{
  5. while (true){
  6. try {
  7. System.out.println("go on ...");
  8. TimeUnit.SECONDS.sleep(1);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. });
  14. t1.start();
  15. TimeUnit.SECONDS.sleep(5);
  16. t1.suspend();//暂停
  17. TimeUnit.SECONDS.sleep(3);
  18. t1.resume();//继续
  19. }
  20. }

        利用volatile控制线程:

  1. public class TestThread {
  2. private static volatile boolean runFlag = true;
  3. @SneakyThrows
  4. public static void main(String[] s){
  5. Thread t = new Thread(()->{
  6. long i = 0L;
  7. while (runFlag){
  8. i++;
  9. }
  10. System.out.println("run end and i="+i);
  11. //第一次运行 输出:run end and i=3574874025
  12. //第二次运行 输出:run end and i=3587827843
  13. });
  14. t.start();
  15. TimeUnit.SECONDS.sleep(1);
  16. runFlag = false;
  17. }
  18. }

        上面的代码是用volatile修饰的变量来判断是否结束线程,是比较优雅的结束线程,但你很难精确的控制线程运行了多少次才结束,所以你只要不依赖线程的中间状态来判断释放结束,volatile还是比较可以的;

        利用interrup来结束线程:

  1. public class TestThread {
  2. @SneakyThrows
  3. public static void main(String[] s){
  4. Thread t = new Thread(()->{
  5. while (!Thread.interrupted()){
  6. }
  7. System.out.println("t end !");
  8. });
  9. t.start();
  10. TimeUnit.SECONDS.sleep(1);
  11. t.interrupt();
  12. }
  13. }

        Interrupt设置标志位来打断线程跟volatile类似;interrupt更优雅一点,因为在线程sleep,wait,join的时候interrupt可以捕获异常来做进一步处理(比如做中断线程的处理),但是volatile是判断不了的只能等待、死等,不能跳到下一次循环去读取running变量的值;

        利用interrupt()和isInterrupted优雅的结束线程

  1. public class TestThread {
  2. @SneakyThrows
  3. public static void main(String[] s){
  4. Thread t = new Thread(()->{
  5. for (;;){
  6. if (Thread.currentThread().isInterrupted()){
  7. System.out.println("Thread is interrupted!");
  8. System.out.println(Thread.currentThread().isInterrupted());
  9. break;
  10. }
  11. }
  12. });
  13. t.start();
  14. TimeUnit.SECONDS.sleep(2);
  15. t.interrupt();
  16. }
  17. }

        总结结束线程的方法:

1. 自然结束(能自然结束尽量自然结束)

2. stop() suspend() resume() 等方式结束

3. 通过判断volatile标志来结束

         a. 不适合某些场景(比如volatile变量还没同步的时候线程就做了阻塞,则没有办法循环回去)

        b. 打断时间不精准,比如一个阻塞集合,容量为1000的时候希望结束线程不要再添加,但是由于volatile同步线程标志位的时间控制的不是很精准,有可能线程还要继续跑一会儿才会停止。

4. 利用interrupt() 和 isInterrupted() 来优雅的控制线程的结束。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/1004217
推荐阅读
相关标签
  

闽ICP备14008679号