本文内容部分引自《Java多线程编程核心技术》,感谢作者!!!
代码地址:https://github.com/xianzhixianzhixian/thread.git
为什么线程暂停不用suspend()和resume()了?因为这两个方法有独占和不同步的问题,先说说“独占”
1、线程内部调用suspend()方法却未调用resume()导致的对象锁独占情况,原因在程序备注里
SynchronizedObject.java
package thread.suspend.resume.deallock;
/**
* 测试suspend和resume的缺点--独占
* 原因是当前线程主动暂停,也只能由Thread.currentThread().resume()来恢复运行
* 但是在线程外别的线程没有办法让该线程恢复运行,所以该线程一直处于suspend状态,且占用了object对象的锁,不释放
* @author: xianzhixianzhixian
* @date: 2018-12-11 19:35
*/
public class SynchronizedObject {
/**
* 方法锁
* synchronized 方法锁控制对类成员变量的访问:
* 每个类实例对应一把锁
* 每个synchronized方法都必须获得调用该方法的类实例的”锁“方能执行,否则所属线程阻塞。
*/
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 thread.suspend.resume.deallock;
/**
* @author: xianzhixianzhixian
* @date: 2018-12-11 19:38
*/
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()方法!");
System.out.println("因为printString()方法被a线程锁定并且永远suspend暂停了!");
object.printString();
}
};
thread2.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
2、线程run()函数内部调用了System.out.println();并且在别的线程中调用了该线程的suspend()方法
MyThread.java
package thread.suspend.resume.deallock;
/**
* suspend()和System.out.println()导致的独占问题
* @author: xianzhixianzhixian
* @date: 2018-12-11 20:12
*/
public class MyThread extends Thread {
private long i=0;
@Override
public void run() {
super.run();
while (true){
i++;
System.out.println(i);
}
}
}
MyThreadRun.java
package thread.suspend.resume.deallock;
/**
* 独占的原因是因为PritStream对象的println()方法一直呈暂停状态,并且锁未释放
* 别的线程无法获得PritStream对象锁导致一直暂停
* @author: xianzhixianzhixian
* @date: 2018-12-11 20:13
*/
public class MyThreadRun {
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"字符串无法输出
下面来解释原因:
看看System.out究竟是什么,是System的一个对象
而System.out.println()方法呢,是一个同步的方法?
每当调用System.out.println()方法时,该方法会获得this也就是PrintStream对象的锁(System.out)。而在第二个例子中run()方法中含有System.out.println()方法,当调用thread.suspend()方法时该线程暂停并且未释放PrintStream对象锁,导致main线程无法获得PrintStream对象锁,一直无法输出"main"字符串!