当前位置:   article > 正文

Java多线程3种中断方式和终止方式_implements runnable线程结束

implements runnable线程结束

一、线程中断

Java 中有以3 种方法可以中断正在运行的线程:

  1. 使用(volatile修饰)退出标志,使线程正常退出,也就是当 run() 方法完成后线程中止;
  2. 也可使用 Atomic 变量作为退出标志,同样可以实现线程的中断;
  3. 使用 interrupt() 方法中断线程(只是中断线程执行,终止线程的睡眠(唤醒),并未终止线程)

1.volatile修饰的标记位

        定义一个boolean型的标志位,在线程的run方法中根据这个标志位是true还是false来判断是否退出

  1. /**
  2. * 使用标志位终止线程
  3. * */
  4. public class ThreadStop {
  5. public static void main(String[] args) {
  6. ThreadStopRunnable runnable = new ThreadStopRunnable();
  7. Thread t = new Thread(runnable);
  8. t.setName("t");
  9. t.start();
  10. try {
  11. Thread.sleep(1000 * 5);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. //执行5秒之后终止线程,终止t线程的执行,将标记修改为false即可
  16. runnable.runFlag = false;
  17. System.out.println(Thread.currentThread().getName() + "\t" + "main is over");
  18. }
  19. }
  20. class ThreadStopRunnable implements Runnable {
  21. //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
  22. public volatile boolean runFlag = true;
  23. @Override
  24. public void run() {
  25. for (int i = 1; i <= 100; i++) {
  26. if (runFlag){
  27. System.out.println(Thread.currentThread().getName() + "---->" + i);
  28. try {
  29. Thread.sleep(1000);
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }else {
  34. //执行终止线程之前的代码,如保存数据等
  35. return;
  36. }
  37. }
  38. }
  39. }

2.AtomicBoolean标记位

        可以使用AtomicBoolean作为标记位,省去volatile关键字修饰。

  1. /**
  2. * 使用标志位终止线程
  3. * */
  4. public class ThreadStop {
  5. public static void main(String[] args) {
  6. ThreadStopRunnable runnable = new ThreadStopRunnable();
  7. Thread t = new Thread(runnable);
  8. t.setName("t");
  9. t.start();
  10. try {
  11. Thread.sleep(1000 * 5);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. //执行5秒之后终止线程,终止t线程的执行,将标记修改为false即可
  16. runnable.runFlag.set(false);
  17. System.out.println(Thread.currentThread().getName() + "\t" + "main is over");
  18. }
  19. }
  20. class ThreadStopRunnable implements Runnable {
  21. //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
  22. public AtomicBoolean runFlag = new AtomicBoolean(true);
  23. @Override
  24. public void run() {
  25. for (int i = 1; i <= 100; i++) {
  26. if (runFlag.get()){
  27. System.out.println(Thread.currentThread().getName() + "---->" + i);
  28. try {
  29. Thread.sleep(1000);
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }else {
  34. //执行终止线程之前的代码,如保存数据等
  35. return;
  36. }
  37. }
  38. }
  39. }

3.interrupt() 中断

        使用interrupt()方法,仅仅是给线程打上中断标记位,并没有实际中断线程(把中断的权利交给线程本身,更安全)

        interrupt() 正在睡眠的线程会抛出InterruptedException异常。

  1. /**
  2. * 使用标志位终止线程
  3. * */
  4. public class ThreadStop {
  5. public static void main(String[] args) {
  6. ThreadStopRunnable runnable = new ThreadStopRunnable();
  7. Thread t = new Thread(runnable);
  8. t.setName("t");
  9. t.start();
  10. try {
  11. Thread.sleep(1000 * 5);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. t.interrupt();
  16. System.out.println(Thread.currentThread().getName() + "\t" + "main is over");
  17. }
  18. }
  19. class ThreadStopRunnable implements Runnable {
  20. @Override
  21. public void run() {
  22. for (int i = 1; i <= 100; i++) {
  23. if (!Thread.currentThread().isInterrupted()){
  24. System.out.println(Thread.currentThread().getName() + "---->" + i);
  25. try {
  26. Thread.sleep(1000);
  27. } catch (InterruptedException e) {
  28. Thread.currentThread().interrupt();
  29. e.printStackTrace();
  30. }
  31. }else {
  32. //执行终止线程之前的代码,如保存数据等
  33. return;
  34. }
  35. }
  36. }
  37. }

t---->1
t---->2
t---->3
t---->4
t---->5
main    main is over
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at org.mark.spring.test.ThreadStopRunnable.run(ThreadStop.java:35)
    at java.lang.Thread.run(Thread.java:748)

二、线程终止

        通过查看 JDK 的 API,我们会看到 java.lang.Thread 类型提供了一系列的方法如 start()、stop()、resume()、suspend()、destory()等方法来管理线程。但是除了 start() 之外,其它方法都被声名为已过时(deprecated)

        虽然 stop() 方法确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且该方法已被弃用,最好不要使用它。
JDK 文档中还引入用一篇文章来解释了弃用这些方法的原因:《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?》

为何弃用stop:

1、调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭

2、调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号