暂停线程意味着此线程还可以恢复运行。在java多线程中,可以使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
public class Thread08 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 ++;
}
}
}
public static void main(String[] args) {
thread08();
}
private static void thread08() {
try{
Thread08 thread = new Thread08();
thread.start();
Thread.sleep(5000);
// A
thread.suspend(); // stop thread
log("A=" + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
log("A=" + System.currentTimeMillis() + " i=" + thread.getI());
// B
thread.resume(); // restart thread
Thread.sleep(5000);
// C
thread.suspend(); //stop thread
log("B=" + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
log("B=" + System.currentTimeMillis() + " i=" + thread.getI());
} catch(InterruptedException e) {
e.printStackTrace();
}
}
输出结果:
A=1496460488867 i=2618846879
A=1496460493868 i=2618846879
B=1496460498874 i=5229661166
B=1496460503876 i=5229661166
程序并没有退出,还在等待状态。
suspend与resume方法的缺点--独占
在使用suspend与resume方法时,如果使用不当,极易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象。
public class Thread09 {
// 同步资源
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 static void main(String[] args) {
thread09();
}
private static void thread09() {
try{
final Thread09 object = new Thread09();
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() {
log("thread2 启动了,但进入不了printString方法,只打印了一个begin!");
log("因为printString方法被a线程锁定并且永远suspend暂停了!");
object.printString();
}
};
thread2.start();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
输出结果:
begin
a线程永远 suspend 了!
thread2 启动了,但进入不了printString方法,只打印了一个begin!
因为printString方法被a线程锁定并且永远suspend暂停了!
程序并没有退出,还在等待状态。
还有另一种独占锁得情况也要格外注意。
public class Thread10 extends Thread {
private long i = 0;
@Override
public void run() {
while(true) {
i++;
System.out.println("i=" + i);
}
}
}
public static void main(String[] args) {
thread10();
}
private static void thread10() {
try{
Thread10 thread = new Thread10();
thread.start();
Thread.sleep(1000);
thread.suspend();
log("main end!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
输出结果:
......
i=129960
i=129961
i=129962
i=129963
i=129964
并没有输出 main end,因为
System.out.println()方法源码如下,Thread10对象suspend暂停得时候不会释放System.out.println()的同步锁,所以main方法就一直得不到System.out.println()的同步锁,也就一直不打印main end了。
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
suspend造成的数据不同步问题
public class Thread11 {
private String username = "name";
private String password = "pwd";
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 printUP() {
System.out.println(username + " " + password);
}
}
public static void main(String[] args) {
thread11();
}
private static void thread11() {
try{
final Thread11 object = new Thread11();
Thread thread1 = new Thread() {
@Override
public void run() {
object.setValue("a_name", "a_pwd");
}
};
thread1.setName("a");
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread() {
@Override
public void run() {
object.printUP();
}
};
thread2.start();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
输出结果:
停止 a 线程!
a_name pwd
程序并没有退出,还在等待状态。
可以看到以上输出的password是初始化时的值,thread1并没有赋值成功,只是赋值了username的值。
yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU的执行时间。但放弃的时间不确定,有可能刚刚放弃,马上有获得CPU时间片。
public class Thread12 extends Thread{
@Override
public void run() {
long beginTime = System.currentTimeMillis();
int count = 0;
for(int i = 0; i < 1000000; ++ i) {
// Thread.yield();
count = count + (i + 1);
}
long endTime = System.currentTimeMillis();
System.out.println("用时:" + (endTime - beginTime) + "毫秒!");
}
}
public static void main(String[] args) {
thread12();
}
private static void thread12() {
Thread12 thread = new Thread12();
thread.start();
}
输出结果:
用时:4毫秒!
解开Thread.yield();注释再次运行:
用时:213毫秒!