上QQ阅读APP看书,第一时间看更新
1.12.2 方法suspend()与resume()的缺点——独占
如果suspend()与resume()方法使用不当,极易造成公共同步对象被独占,其他线程无法访问公共同步对象的结果。
创建suspend_resume_deal_lock项目,文件SynchronizedObject.java代码如下:
package testpackage; public class SynchronizedObject { synchronized public void printString() { System.out.println("begin"); if (Thread.currentThread().getName().equals("a")) { System.out.println("a线程永远 suspend了!"); Thread.currentThread().suspend(); } System.out.println("end"); } }
文件Run.java代码如下:
package test.run; import testpackage.SynchronizedObject; public class Run { public static void main(String[] args) { try { final SynchronizedObject object = new SynchronizedObject(); Thread thread1 = new Thread() { @Override public void run() { object.printString(); } }; thread1.setName("a"); thread1.start(); Thread.sleep(1000); Thread thread2 = new Thread() { @Override public void run() { System.out .println("thread2启动了,但进入不了printString()方法!只打印 1个begin"); System.out .println("因为printString()方法被a线程锁定并且永远的suspend 暂停了!"); object.printString(); } }; thread2.start(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
程序运行结果如图1-55所示。
图1-55 独占并锁死printString()方法
另外一种独占锁的情况也需要格外注意,稍有不注意,就会掉进“坑”里。创建测试项目suspend_resume_LockStop,类MyThread.java代码如下:
package mythread; public class MyThread extends Thread { private long i = 0; @Override public void run() { while (true) { i++; } } }
类Run.java代码如下:
package test.run; import mythread.MyThread; public class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(1000); thread.suspend(); System.out.println("main end!"); } catch (InterruptedException e) { e.printStackTrace(); } } }
程序运行结果如图1-56所示。
图1-56 控制台输出main end信息
进程状态在控制台中呈红色按钮显示,说明进程并未销毁。虽然main线程销毁了,但是MyThread呈暂停状态,所以进程不会销毁。
如果将线程类MyThread.java更改如下:
package mythread; public class MyThread extends Thread { private long i = 0; @Override public void run() { while (true) { i++; System.out.println(i); } } }
再次运行程序,则控制台不会输出main end,运行结果如图1-57所示。
图1-57 不输出main end信息
出现这种情况的原因是当程序运行到System.out.println(i)方法内部被暂停时,同步锁是不释放的。println()方法的源代码如图1-58所示。
图1-58 锁不释放
当前PrintStream对象的println()方法一直呈“暂停”状态,并且“锁未释放”,而main()方法中的代码“System.out.println("main end!");”也需要这把锁,main线程并未销毁,导致不能输出“main end!”。
虽然suspend()方法是过期作废的方法,但研究其过期作废的原因还是很有必要的。