ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java暂停/挂起线程(suspend())和恢复线程(resume())

2019-07-11 21:08:40  阅读:196  来源: 互联网

标签:suspend Java Thread System 线程 println public


暂停线程意味着此线程还可以恢复运行。在 Java 多线程中,可以使用 suspend() 方法暂停线程,使用 resume() 方法恢复线程的执行。

suspend() 与 resume() 方法

本节通过一个案例来介绍 suspend() 与 resume() 方法的用法。首先来看一下案例中使用到的 MyThread21 线程,代码如下所示。


 
  1. package ch14;
  2. public class MyThread21 extends Thread
  3. {
  4. private long i=0;
  5. public long getI()
  6. {
  7. return i;
  8. }
  9. public void setI(long i)
  10. {
  11. this.i=i;
  12. }
  13. @Override
  14. public void run()
  15. {
  16. while(true)
  17. {
  18. i++;
  19. }
  20. }
  21. }


MyThread21 线程中有一个成员 i,其中 setI() 方法和 getI() 方法分别用于设置和获取 i 的值,run() 方法则是一个从i开始递增的死循环。

下面编写主线程的代码,具体如下所示。


 
  1. package ch14;
  2. public class Test25
  3. {
  4. public static void main(String[] args)
  5. {
  6. try
  7. {
  8. MyThread21 thread=new MyThread21();
  9. thread.start();
  10. Thread.sleep(5000);
  11. //A段
  12. thread.suspend();
  13. System.out.println("A= "+System.currentTimeMillis()+" i= "+thread.getI());
  14. Thread.sleep(5000);
  15. System.out.println("A= "+System.currentTimeMillis()+" i= "+thread.getI());
  16. //B段
  17. thread.resume();
  18. Thread.sleep(5000);
  19. //C段
  20. thread.suspend();
  21. System.out.println("B= "+System.currentTimeMillis()+" i= "+thread.getI());
  22. Thread.sleep(5000);
  23. System.out.println("B= "+System.currentTimeMillis()+" i= "+thread.getI());
  24. }
  25. catch(InterruptedException e)
  26. {
  27. e.printStackTrace();
  28. }
  29. }
  30. }


最终运行结果如下所示。

A= 1540978346179 i= 2680986095
A= 1540978351179 i= 2680986095
B= 1540978356179 i= 5348657508
B= 1540978361179 i= 5348657508


从输出结果的时间来看,调用 suspend() 方法确实可以暂停线程,而在调用 resume() 方法后线程恢复运行状态。

独占问题

在使用 suspend() 方法与 resume() 方法时,如果使用不当极易造成公共的同步对象被独占,从而使得其他线程无法访问公共同步对象。

例 2

下面通过一个案例来演示这种情况。如下所示是案例中使用的公共对象的代码。


 
  1. package ch14;
  2. public class SynchronizedObject1
  3. {
  4. synchronized public void printString()
  5. {
  6. System.out.println("begin");
  7. if (Thread.currentThread().getName().equals("a"))
  8. {
  9. System.out.println("a线程永远 suspend了!");
  10. Thread.currentThread().suspend();
  11. }
  12. System.out.println("end");
  13. }
  14. }


SynchronizedObject1 类在 printString() 方法开始时输出“begin”,在该方法结束时输出“end”,方法体中的if判断如果当前线程的名称是 a 则调用 suspend() 方法暂停线程。

接下来编写主线程代码,在主线程中创建一个 SynchronizedObject1 类对象并在线程中调用 printString() 方法,具体代码如下所示。


 
  1. package ch14;
  2. public class Test26
  3. {
  4. public static void main(String[] args)
  5. {
  6. try
  7. {
  8. final SynchronizedObject1 object=new SynchronizedObject1();
  9. Thread thread1=new Thread()
  10. {
  11. @Override
  12. public void run()
  13. {
  14. object.printString();
  15. }
  16. };
  17. thread1.setName("a");
  18. thread1.start();
  19. Thread.sleep(1000);
  20. Thread thread2=new Thread()
  21. {
  22. @Override
  23. public void run()
  24. {
  25. System.out.println("thread2启动了,但进入不了printString()方法!所以只会打印1个begin!");
  26. System.out.println("因为printString()方法被a线程锁定并且永远暂停了!");
  27. object.printString();
  28. }
  29. };
  30. thread2.start();
  31. }
  32. catch(InterruptedException e)
  33. {
  34. // TODO Auto-generated catch block
  35. e.printStackTrace();
  36. }
  37. }
  38. }


上述代码比较简单这里就不再解释,运行后的结果如下所示。从中可以看到由于线程被永久暂停,所以只会输出一个 begin。

begin
a线程永远 suspend了!
thread2启动了,但进入不了printString()方法!所以只会打印1个begin!
因为printString()方法被a线程锁定并且永远暂停了!

例 3

还有另外一种独占锁的情况也要格外注意,稍有不慎就会掉进“坑”里。创建测试用的 MyThread22 线程,具体代码如下:


 
  1. package ch14;
  2. public class MyThread22 extends Thread
  3. {
  4. private long i=0;
  5. @Override
  6. public void run()
  7. {
  8. while (true)
  9. {
  10. i++;
  11. }
  12. }
  13. }


再来看主线程的代码,如下所示。


 
  1. package ch14;
  2. public class Test27
  3. {
  4. public static void main(String[] args)
  5. {
  6. try
  7. {
  8. MyThread22 thread=new MyThread22();
  9. thread.start();
  10. Thread.sleep(1000);
  11. thread.suspend();
  12. System.out.println("main end!");
  13. }
  14. catch(InterruptedException e)
  15. {
  16. e.printStackTrace();
  17. }
  18. }
  19. }


程序执行后将看到预料不到的结果,如下所示。

main end!


如果将 MyThread22 线程类的代码更改如下:


 
  1. package ch14;
  2. public class MyThread22 extends Thread
  3. {
  4. private long i=0;
  5. @Override
  6. public void run()
  7. {
  8. while(true)
  9. {
  10. i++;
  11. System.out.println(i);
  12. }
  13. }
  14. }


再次运行程序,控制台将不打印 main end,运行结果如下所示。

......
130862
130863
130864
130865
130866
130867


出现这种情况的原因是,当程序运行到 println() 方法内部停止时,同步锁未被释放。这导致当前 PrintStream 对象的 println() 方法一直呈“暂停”状态,并且“锁未释放”,而 main() 方法中的代码“System.out. println(Mmain end!'1);”迟迟不能执行打印。

提示:虽然 suspend() 方法是过期作废的方法,但还是有必要研究它过期作废的原因,这是很有意义的。

不同步问题

在使用 suspend() 方法与 resume() 方法时也容易出现因为线程的暂停而导致数据不同步的情况。

例 4

下面通过一个案例来演示这种情况。如下所示是案例中使用的公共对象的代码。


 
  1. package ch14;
  2. public class MyObject
  3. {
  4. private String username="1";
  5. private String password="11";
  6. public void setValue(String u,String p)
  7. {
  8. this.username=u;
  9. if(Thread.currentThread().getName().equals("a"))
  10. {
  11. System.out.println("停止a线程!");
  12. Thread.currentThread().suspend();
  13. }
  14. this.password=p;
  15. }
  16. public void printUsernamePassword()
  17. {
  18. System.out.println(username+" "+password);
  19. }
  20. }


如上述代码所示,MyObject 类的 setValue() 方法会在线程名称是 a 时执行停止线程操作。 如下所示是主线程代码。


 
  1. package ch14;
  2. public class Test28
  3. {
  4. public static void main(String[] args) throws InterruptedException
  5. {
  6. final MyObject myobject=new MyObject();
  7. Thread thread1=new Thread()
  8. {
  9. public void run()
  10. {
  11. myobject.setValue("a","aa");
  12. };
  13. };
  14. thread1.setName("a");
  15. thread1.start();
  16. Thread.sleep(500);
  17. Thread thread2=new Thread()
  18. {
  19. public void run()
  20. {
  21. myobject.printUsernamePassword();
  22. };
  23. };
  24. thread2.start();
  25. }
  26. }


程序运行结果如下所示。

停止a线程!
a 11


从程序运行的结果可以看到,出现了值不同步的情况,所以在程序中使用 suspend() 方法要格外注意。

标签:suspend,Java,Thread,System,线程,println,public
来源: https://blog.csdn.net/jijiangpeng/article/details/95519848

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有