在使用suspend与resume方法时,如果使用不当,极易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象。
/**
* @author wuyoushan
* @date 2017/3/27.
*/
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");
}
}
/**
* @author wuyoushan
* @date 2017/3/20.
*/
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){
e.printStackTrace();
}
}
}
运行结果为:
begin
a线程永远suspend了!
thread2启动了,但进入不了printString()方法!只打印1个begin
因为printString()方法被a线程锁定并且永远suspend暂停了!
还有另外一种独占锁的情况也要格外的注意,稍有不慎,就会掉进“坑”里。
/**
* MyThread线程测试
* @author wuyoushan
* @date 2017/3/21.
*/
public class MyThread extends Thread {
private long i=0;
@Override
public void run() {
while (true){
i++;
}
}
}
/**
* @author wuyoushan
* @date 2017/3/20.
*/
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();
}
}
}
运行结果为:
main end!
如果将线程类MyThread.java更改如下:
/**
* MyThread线程测试
* @author wuyoushan
* @date 2017/3/21.
*/
public class MyThread extends Thread {
private long i=0;
@Override
public void run() {
while (true){
i++;
System.out.println("i="+i);
}
}
}
再次运行程序,控制台将不打印main end,运行结果如下
i=98713
i=98714
i=98715
i=98716
i=98717
i=98718
i=98719
出现这样结果的原因是,当程序运行到println()方法内部停止时,同步锁未被释放。方法println()源代码如下:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
这导致当前PrintStream对象的println()方法一直呈“暂停”状态,并且“锁未释放”,
而main()方法中的代码System.out.println("main end!");迟迟不能执行打印。
虽然suspuend()方法是过期作废的方法,但还是有必要研究它过期作废的原因,这是很有意义的。
摘选自 java多线程核心编程技术-1.8.2