暂停线程意味着此线程还可以恢复运行
在 Java 多线程中,可以使用 suspend()方法暂停线程,使用 resume() 方法来恢复线程的执行。
本节将讲述suspend()方法与resume()方法的使用
文件 MyThread.java代码
package test1_12;
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++;
}
}
}
文件Run.java代码
package test1_12;
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(5000);
// A段
thread.suspend();
System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
// B段
thread.resume();
Thread.sleep(5000);
// C段
thread.suspend();
System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果
从控制台输出的时间上来看,线程的确被暂停了,而 且可以恢复成运行状态。
stop()方法用于销毁线程对象,如果想继续运行线程, 则必须使用start()方法重新启动线程,
而suspend()方法用于让线程不再执行任务,线程对象并不销毁,在当前所执行 的代码处暂停,未来还可以恢复运行。
suspend()方法与resume()方法的缺点——独占
如果 suspend() 方法与 resume()方法使用不当,极易造成公共同步对象被 独占,其他线程无法访问公共同步对象的结果。
文件SynchronizedObject.java代码
package test1_12.test1;
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 test1_12.test1;
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();
}
}
}
运行结果
另外一种独占锁的情况也需要格外注意,稍有不注意,就会掉 进“坑”里。
类MyThread.java 代码
package test1_12.test2;
public class MyThread extends Thread {
private long i = 0;
@Override
public void run() {
while (true) {
i++;
}
}
}
类Run.java代码
package test1_12.test2;
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 线程销毁了,但是 MyThread 呈暂停状态,所以进程不会销毁。
但如果将线程类MyThread.java更改如下
package test1_12.test3;
public class MyThread extends Thread {
private long i = 0;
@Override
public void run() {
while (true) {
i++;
System.out.println(i);
}
}
}
运行结果
再次运行程序,控制台不输出 main end
出现这种情况的原因是当程序运行到System.out.println (i)方法内部 停止时,同步锁是不释放的
println()方法源代码
/**
* Prints a String and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(String)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x The <code>String</code> to be printed.
*/
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
当前 PrintStream 对象的 println() 方法一直呈 “ 暂停 ” 状态,并且 “锁未释 放 ” ,而 main() 方法中的代码 “System.out.println ( "main end ! " ); ”也需要 这把锁, main 线程并未销毁,造成迟迟不能输出 main end。
虽然 suspend() 方法是过期作废的方法,但研究其过期作废的原因是很
有必要的。
suspend()方法与resume()方法的缺点—— 数据不完整
在使用suspend()方法与resume()方法时也容易出现线 程暂停,进而导致数据不完整的情况。
文件 MyObject.java代码
package test1_12.test4;
public class MyObject {
private String username = "1";
private String password = "11";
public void setValue(String u, String p) {
this.username = u;
if (Thread.currentThread().getName().equals("a")) {
System.out.println("停止a线程!");
Thread.currentThread().suspend();
}
this.password = p;
}
public void printUsernamePassword() {
System.out.println(username + " " + password);
}
}
文件Run.java代码
package test1_12.test4;
public class Run {
public static void main(String[] args) throws InterruptedException {
final MyObject myobject = new MyObject();
Thread thread1 = new Thread() {
public void run() {
myobject.setValue("a", "aa");
}
;
};
thread1.setName("a");
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread() {
public void run() {
myobject.printUsernamePassword();
}
;
};
thread2.start();
}
}
运行结果
程序运行结果出现值不完整的情况,所以在程序中使 用 suspend() 方法要格外注意。
这两个方法被标识为作废过期的,想要实现对线程进 行暂停与恢复的处理,可使用 wait() 、 notify() 或notifyAll() 方法