一:简介
暂停线程意味着此线程还可以恢复运行。通过suspend()函数,可使线程进入停滞状态。
通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回
可执行状态。注意如果在线程没有挂起时(就是没有调用suspend()方法前)去调用
Resume()方法会出现异常,所以使用这样的方法进行线程线程同步已经不推荐使用了。
二:简单案例演示
- 创建MyThread类
package com.kgf.test; public class MyThread extends Thread { private long i = 0; public long getI() { return i; } public void setI(long i) { this.i = i; } @Override public void run() { while(true) { i++; } } }
- 创建测试类
package com.kgf.test; public class Run { public static void main(String[] args) throws InterruptedException { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(2000); //A段 thread.suspend();//暂停 System.out.println("A1="+System.currentTimeMillis()+" i="+thread.getI()); Thread.sleep(2000); System.out.println("A2="+System.currentTimeMillis()+" i="+thread.getI()); //B段 thread.resume();//释放 Thread.sleep(2000); //C段 thread.suspend();//暂停 System.out.println("C1="+System.currentTimeMillis()+" i="+thread.getI()); Thread.sleep(2000); System.out.println("C2="+System.currentTimeMillis()+" i="+thread.getI()); } catch (Exception e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("==========END================"); } }
- 效果
从控制台的打印时间上来看,线程的确被暂停了,而且还可以恢复为运行的状态。
三:suspend与resume方法的缺点“独占”
- 简介
在使用suspend和resume方法时,如果使用不当,极易造成公共的同步对象
的独占,使其它线程无法访问公共同步对象。 - 简单代码示例1
⑴创建SynchronizedObject类
⑵测试类
package com.kgf.test; public class Run { public static void main(String[] args) throws InterruptedException { try { final SynchronizedObject object = new SynchronizedObject(); Thread thread1 = new Thread() {//创建线程1 @Override public void run() { object.printString();//调用SynchronizedObject中的方法 } }; thread1.setName("a"); thread1.start();//启动线程1 Thread.sleep(1000);//主线程睡眠1秒钟 Thread thread2 = new Thread() {//创建线程2 @Override public void run() { System.out.println("thread2启动了。。。。"); object.printString();//调用SynchronizedObject中的方法 System.out.println("thread2进来了吗?。。。。"); } }; thread2.start();//启动线程2 } catch (Exception e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("==========END================"); } }
⑶效果:
⑷结果分析:
通过上面的代码可知,我们将线程thread1在printString方法中使用suspend方法
暂停后没有释放,最后导致这个方法的锁一直被这个线程所占用,thread2完全无法调用。 - 简单代码示例2
⑴创建MyThread类
⑵测试类
⑶效果
⑷结果分析:
我们可以发现当我们把thread线程暂停后,主线程中的"main end"都没有打印。那么这个
是什么原因导致的呢?我们查看一下printIn()源代码如下:
这个是PrintStream对象中的println方法,是个同步锁的方法,这时候应该就明白了。出现
这样情况的原因是当thread线程程序运行到printIn()方法内部停止时,同步锁未被释放,这
导致当前PrintStream对象的printIn()方法一直呈“暂停”状态。而且这个PrintStream是唯一的,
thread线程里面的没有释放,下面main方法中也无法使用printIn()方法打印。我们可以看一下
System类中的PrintStream对象的定义:
四:suspend与resume方法的缺点“不同步”
- 简介
在使用suspend与resume方法时也容易出现因为线程的暂停而导致数据不同步的情况。 - 代码实例
⑴创建MyObject类
package com.kgf.test; public class MyObject { private String username = "111"; private String password = "222"; public void setValue(String u,String p) { this.username = u; if(Thread.currentThread().getName().equals("a")) { System.out.println("停止a线程!"); Thread.currentThread().suspend();//暂停a线程 } this.password = p; } public void printInfo() { System.out.println(username+" "+password); } }
⑵测试类
package com.kgf.test; public class Run { public static void main(String[] args) throws InterruptedException { try { final MyObject object = new MyObject(); Thread thread1 = new Thread() {//创建线程1 @Override public void run() { object.setValue("a","aa"); } }; thread1.setName("a"); thread1.start();//启动线程1 Thread.sleep(500); Thread thread2 = new Thread() {//创建线程2 @Override public void run() { object.printInfo(); } }; thread2.start();//启动线程2 } catch (Exception e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("==========END================"); } }
⑶ 效果
⑷ 结果分析:
从上面的代码可知a线程执行代码到一半的时候,将对象MyObject中的变量值修改了一个,
然后将线程暂停了,后面线程再打印的时候发现数据已经出现了不同步的问题。