暂停线程意味着此线程还可以恢复运行。在Java多线程中,可以使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
suspend与resume方法的使用
示例代码如下:
public class MyThread extends Thread{
private long i = 0;
@Override
public void run() {
while(true){
i++;
}
}
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
}
}
public class Run {
public static void main(String[] args) {
try{
MyThread t = new MyThread();
t.start();
Thread.sleep(5000);
//A段
t.suspend();
System.out.println("A= " +System.currentTimeMillis()+" i="+t.getI());
Thread.sleep(5000);
System.out.println("A= " +System.currentTimeMillis()+" i="+t.getI());
//B段
t.resume();
Thread.sleep(5000);
//C段
t.suspend();
System.out.println("B= " +System.currentTimeMillis()+" i="+t.getI());
Thread.sleep(5000);
System.out.println("B= " +System.currentTimeMillis()+" i="+t.getI());
}catch(Exception e){
e.printStackTrace();
}
}
}
运行结果:
从控制台的打印的时间来看,线程的确被暂停了,而且还恢复成运行的状态。
suspend与resume方法的缺点-独占
在使用suspend与resume方法时,如果使用不当,极易造成公共的同步对象独占,使其他线程无法访问公共同步对象。示例代码如下:
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");
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
SynchronizedObject s = new SynchronizedObject();
Thread t1 = new Thread(){
@Override
public void run() {
s.printString();
}
};
t1.setName("a");
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(){
@Override
public void run() {
System.out.println("t2 启动了,但进入不printString()方法!");
s.printString();
}
};
t2.start();
}
}
执行结果如下:
还有另外一种独占锁的情况,创建如下代码:
public class MyThread extends Thread{
private long i = 0;
@Override
public void run() {
while(true){
i++;
}
}
}
public class Run2 {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.start();
Thread.sleep(1000);
t.suspend();
System.out.println("main end");
}
}
执行结果如下:
但是如果将代码改为如下:
public class MyThread extends Thread{
private long i = 0;
@Override
public void run() {
while(true){
i++;
System.out.println("i="+i);
}
}
}
则输入结果如下:
控制台并不打印main end。出现这样情况的原因是,当程序运行到println()方法内部停止,同步锁未被释放。在上面也有讲过println()方法内部是同步的。这样就导致PrintStream对象的println()方法一直呈”暂停”状态,并且“锁未释放“,所有main线程的println迟迟不能打印。
suspend与resume方法的缺点-不同步
在使用suspend与resume方法时也很容易出现因为线程的暂停而导致数据不同的情况。示例代码如下:
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);
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyObject m = new MyObject();
Thread t1 = new Thread(){
@Override
public void run() {
m.setValue("a", "aa");
}
};
t1.setName("a");
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(){
@Override
public void run() {
m.printUserNamePassword();
}
};
t2.start();
}
}
运行结果如下: