当前位置:   article > 正文

如何停止一个正在运行的线程_java线程池停止正在执行的任务

java线程池停止正在执行的任务

停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作。停止一个线程可以用Thread.stop()方法,但最好不要用它。虽然它确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且是已被废弃的方法。 在java中有以下3种方法可以终止正在运行的线程:

  1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

  2. 使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。

  3. 使用interrupt方法中断线程。

目录

1.停止不了的线程

2.判断线程是否停滞状态

3.能停止的线程--异常法

4.在沉睡中停止

5.能停止的线程--暴力停止

6.方法stop()与java.lang.ThreadDeath异常

7.释放锁的不良后果

8.使用return停止线程


1.停止不了的线程

interrupt()方法的使用效果并不像for+break语句那样,马上就停止循环。调用interrupt方法是在当前线程中打了一个停止标志,并不是真的停止线程。

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. for(int i=0; i<500000; i++){
  5. System.out.println("i="+(i+1));
  6. }
  7. }
  8. }
  9. public class Run {
  10. public static void main(String args[]){
  11. Thread thread = new MyThread();
  12. thread.start();
  13. try {
  14. Thread.sleep(2000);
  15. thread.interrupt();
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }

输出结果:

  1. ...
  2. i=499994
  3. i=499995
  4. i=499996
  5. i=499997
  6. i=499998
  7. i=499999
  8. i=500000

2.判断线程是否停滞状态

Thread.java类中提供了两种方法:

  1. this.interrupted(): 测试当前线程是否已经中断;

  2. this.isInterrupted(): 测试线程是否已经中断;

那么这两个方法有什么图区别呢? 我们先来看看this.interrupted()方法的解释:测试当前线程是否已经中断,当前线程是指运行this.interrupted()方法的线程。

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. for(int i=0; i<500000; i++){
  5. i++;
  6. // System.out.println("i="+(i+1));
  7. }
  8. }
  9. }
  10. public class Run {
  11. public static void main(String args[]){
  12. Thread thread = new MyThread();
  13. thread.start();
  14. try {
  15. Thread.sleep(2000);
  16. thread.interrupt();
  17. System.out.println("stop 1??" + thread.interrupted());
  18. System.out.println("stop 2??" + thread.interrupted());
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }

运行结果:

  1. stop 1??false
  2. stop 2??false

类Run.java中虽然是在thread对象上调用以下代码:thread.interrupt(), 后面又使用

  1. System.out.println("stop 1??" + thread.interrupted());
  2. System.out.println("stop 2??" + thread.interrupted());

来判断thread对象所代表的线程是否停止,但从控制台打印的结果来看,线程并未停止,这也证明了interrupted()方法的解释,测试当前线程是否已经中断。这个当前线程是main,它从未中断过,所以打印的结果是两个false.

如何使main线程产生中断效果呢?

  1. public class Run2 {
  2. public static void main(String args[]){
  3. Thread.currentThread().interrupt();
  4. System.out.println("stop 1??" + Thread.interrupted());
  5. System.out.println("stop 2??" + Thread.interrupted());
  6. System.out.println("End");
  7. }
  8. }

运行结果为:

  1. stop 1??true
  2. stop 2??false
  3. End

方法interrupted()的确判断出当前线程是否是停止状态。但为什么第2个布尔值是false呢? 官方帮助文档中对interrupted方法的解释:测试当前线程是否已经中断。线程的中断状态由该方法清除。 换句话说,如果连续两次调用该方法,则第二次调用返回false。

下面来看一下inInterrupted()方法。

  1. public class Run3 {
  2. public static void main(String args[]){
  3. Thread thread = new MyThread();
  4. thread.start();
  5. thread.interrupt();
  6. System.out.println("stop 1??" + thread.isInterrupted());
  7. System.out.println("stop 2??" + thread.isInterrupted());
  8. }
  9. }

运行结果为:

  1. stop 1??true
  2. stop 2??true

isInterrupted()并为清除状态,所以打印了两个true。

3.能停止的线程--异常法

有了前面学习过的知识点,就可以在线程中用for语句来判断一下线程是否是停止状态,如果是停止状态,则后面的代码不再运行即可:

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. for(int i=0; i<500000; i++){
  5. if(this.interrupted()) {
  6. System.out.println("线程已经终止, for循环不再执行");
  7. break;
  8. }
  9. System.out.println("i="+(i+1));
  10. }
  11. }
  12. }
  13. public class Run {
  14. public static void main(String args[]){
  15. Thread thread = new MyThread();
  16. thread.start();
  17. try {
  18. Thread.sleep(2000);
  19. thread.interrupt();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }

运行结果:

  1. ...
  2. i=202053
  3. i=202054
  4. i=202055
  5. i=202056
  6. 线程已经终止, for循环不再执行

上面的示例虽然停止了线程,但如果for语句下面还有语句,还是会继续运行的。看下面的例子:

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. for(int i=0; i<500000; i++){
  5. if(this.interrupted()) {
  6. System.out.println("线程已经终止, for循环不再执行");
  7. break;
  8. }
  9. System.out.println("i="+(i+1));
  10. }
  11. System.out.println("这是for循环外面的语句,也会被执行");
  12. }
  13. }

使用Run.java执行的结果是:

  1. ...
  2. i=180136
  3. i=180137
  4. i=180138
  5. i=180139
  6. 线程已经终止, for循环不再执行
  7. 这是for循环外面的语句,也会被执行

如何解决语句继续运行的问题呢? 看一下更新后的代码:

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. try {
  5. for(int i=0; i<500000; i++){
  6. if(this.interrupted()) {
  7. System.out.println("线程已经终止, for循环不再执行");
  8. throw new InterruptedException();
  9. }
  10. System.out.println("i="+(i+1));
  11. }
  12. System.out.println("这是for循环外面的语句,也会被执行");
  13. } catch (InterruptedException e) {
  14. System.out.println("进入MyThread.java类中的catch了。。。");
  15. e.printStackTrace();
  16. }
  17. }
  18. }

使用Run.java运行的结果如下:

  1. ...
  2. i=203798
  3. i=203799
  4. i=203800
  5. 线程已经终止, for循环不再执行
  6. 进入MyThread.java类中的catch了。。。
  7. java.lang.InterruptedException
  8. at thread.MyThread.run(MyThread.java:13)

4.在沉睡中停止

如果线程在sleep()状态下停止线程,会是什么效果呢?

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. try {
  5. System.out.println("线程开始。。。");
  6. Thread.sleep(200000);
  7. System.out.println("线程结束。");
  8. } catch (InterruptedException e) {
  9. System.out.println("在沉睡中被停止, 进入catch, 调用isInterrupted()方法的结果是:" + this.isInterrupted());
  10. e.printStackTrace();
  11. }
  12. }
  13. }

使用Run.java运行的结果是:

  1. 线程开始。。。
  2. 在沉睡中被停止, 进入catch, 调用isInterrupted()方法的结果是:false
  3. java.lang.InterruptedException: sleep interrupted
  4. at java.lang.Thread.sleep(Native Method)
  5. at thread.MyThread.run(MyThread.java:12)

从打印的结果来看, 如果在sleep状态下停止某一线程,会进入catch语句,并且清除停止状态值,使之变为false。

前一个实验是先sleep然后再用interrupt()停止,与之相反的操作在学习过程中也要注意:

  1. public class MyThread extends Thread {
  2. public void run(){
  3. super.run();
  4. try {
  5. System.out.println("线程开始。。。");
  6. for(int i=0; i<10000; i++){
  7. System.out.println("i=" + i);
  8. }
  9. Thread.sleep(200000);
  10. System.out.println("线程结束。");
  11. } catch (InterruptedException e) {
  12. System.out.println("先停止,再遇到sleep,进入catch异常");
  13. e.printStackTrace();
  14. }
  15. }
  16. }
  17. public class Run {
  18. public static void main(String args[]){
  19. Thread thread = new MyThread();
  20. thread.start();
  21. thread.interrupt();
  22. }
  23. }

运行结果:

  1. i=9998
  2. i=9999
  3. 先停止,再遇到sleep,进入catch异常
  4. java.lang.InterruptedException: sleep interrupted
  5. at java.lang.Thread.sleep(Native Method)
  6. at thread.MyThread.run(MyThread.java:15)

5.能停止的线程--暴力停止

使用stop()方法停止线程则是非常暴力的。

  1. public class MyThread extends Thread {
  2. private int i = 0;
  3. public void run(){
  4. super.run();
  5. try {
  6. while (true){
  7. System.out.println("i=" + i);
  8. i++;
  9. Thread.sleep(200);
  10. }
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. }
  16. public class Run {
  17. public static void main(String args[]) throws InterruptedException {
  18. Thread thread = new MyThread();
  19. thread.start();
  20. Thread.sleep(2000);
  21. thread.stop();
  22. }
  23. }

运行结果:

  1. i=0
  2. i=1
  3. i=2
  4. i=3
  5. i=4
  6. i=5
  7. i=6
  8. i=7
  9. i=8
  10. i=9
  11. Process finished with exit code 0

6.方法stop()与java.lang.ThreadDeath异常

调用stop()方法时会抛出java.lang.ThreadDeath异常,但是通常情况下,此异常不需要显示地捕捉。

  1. public class MyThread extends Thread {
  2. private int i = 0;
  3. public void run(){
  4. super.run();
  5. try {
  6. this.stop();
  7. } catch (ThreadDeath e) {
  8. System.out.println("进入异常catch");
  9. e.printStackTrace();
  10. }
  11. }
  12. }
  13. public class Run {
  14. public static void main(String args[]) throws InterruptedException {
  15. Thread thread = new MyThread();
  16. thread.start();
  17. }
  18. }

stop()方法以及作废,因为如果强制让线程停止有可能使一些清理性的工作得不到完成。另外一个情况就是对锁定的对象进行了解锁,导致数据得不到同步的处理,出现数据不一致的问题。

7.释放锁的不良后果

  1. public class SynchronizedObject {
  2. private String name = "a";
  3. private String password = "aa";
  4. public synchronized void printString(String name, String password){
  5. try {
  6. this.name = name;
  7. Thread.sleep(100000);
  8. this.password = password;
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public String getPassword() {
  20. return password;
  21. }
  22. public void setPassword(String password) {
  23. this.password = password;
  24. }
  25. }
  26. public class MyThread extends Thread {
  27. private SynchronizedObject synchronizedObject;
  28. public MyThread(SynchronizedObject synchronizedObject){
  29. this.synchronizedObject = synchronizedObject;
  30. }
  31. public void run(){
  32. synchronizedObject.printString("b", "bb");
  33. }
  34. }
  35. public class Run {
  36. public static void main(String args[]) throws InterruptedException {
  37. SynchronizedObject synchronizedObject = new SynchronizedObject();
  38. Thread thread = new MyThread(synchronizedObject);
  39. thread.start();
  40. Thread.sleep(500);
  41. thread.stop();
  42. System.out.println(synchronizedObject.getName() + " " + synchronizedObject.getPassword());
  43. }
  44. }

输出结果:b aa

由于stop()方法以及在JDK中被标明为“过期/作废”的方法,显然它在功能上具有缺陷,所以不建议在程序张使用stop()方法。

8.使用return停止线程

将方法interrupt()与return结合使用也能实现停止线程的效果:

  1. public class MyThread extends Thread {
  2. public void run(){
  3. while (true){
  4. if(this.isInterrupted()){
  5. System.out.println("线程被停止了!");
  6. return;
  7. }
  8. System.out.println("Time: " + System.currentTimeMillis());
  9. }
  10. }
  11. }
  12. public class Run {
  13. public static void main(String args[]) throws InterruptedException {
  14. Thread thread = new MyThread();
  15. thread.start();
  16. Thread.sleep(2000);
  17. thread.interrupt();
  18. }
  19. }

输出结果:

  1. ...
  2. Time: 1467072288503
  3. Time: 1467072288503
  4. Time: 1467072288503
  5. 线程被停止了!

不过还是建议使用“抛异常”的方法来实现线程的停止,因为在catch块中还可以将异常向上抛,使线程停止事件得以传播。

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

闽ICP备14008679号