在java中,使用suspend()方法暫停線程,使用resume()方法恢複線程的執行。 1.8.1suspend與resume的使用: 線程代碼: 執行代碼: 執行結果: 從執行的時間來看,新開啟的線程確實發生了暫停(當前線程暫停與啟動的時間與另外開啟的線程是一致的),並且能夠成功的恢復運行狀態 ...
在java中,使用suspend()方法暫停線程,使用resume()方法恢複線程的執行。
1.8.1suspend與resume的使用:
線程代碼:
public class Thread1 extends Thread {
private long i = 0L;
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
}
@Override
public void run() {
while (true) {
i++;
}
}
}
執行代碼:
public class Main {
public static void main(String[] args) {
try {
Thread1 thread = new Thread1();
thread.start();
Thread.sleep(1000);
//A段
thread.suspend();
System.out.println("A = " + System.currentTimeMillis() + " I = " +thread.getI());
//B段
thread.resume();
Thread.sleep(1000);
//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();
}
}
}
執行結果:
從執行的時間來看,新開啟的線程確實發生了暫停(當前線程暫停與啟動的時間與另外開啟的線程是一致的),並且能夠成功的恢復運行狀態。
1.8.2suspend與resume方法的缺點——獨占:
在使用suspend與resume方法時,可能會導致公共的同步對象的獨占發生,使得其他線程無法訪問公共同步對象。
獨占代碼:
public class SynchronizedObject {
synchronized public void printString() {
System.out.println("begin");
if ("a".equals(Thread.currentThread().getName())) {
System.out.println("a線程永遠的暫停了,suspend");
Thread.currentThread().suspend();
}
System.out.println("end");
}
}
執行代碼:
public class Main {
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("因為在Thread1中已經暫停了,後面的語句無法執行,所有隻列印了begin");
System.out.println("因為此時Thread1已經進入了線程並且鎖定了方法printString()所以什麼都打不出來");
System.out.println("這是死鎖的一種表現");
object.printString();
}
};
thread2.setName("a");
thread2.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
另一種陷阱式的多線程獨占問題
線程代碼:
public class Thread2 extends Thread {
private long i = 0L;
@Override
public void run() {
while (true) {
i++;
System.out.println(i);
}
}
}
執行代碼:
public class Main {
public static void main(String[] args) {
try {
Thread2 thread = new Thread2();
thread.start();
Thread.sleep(1000);
thread.suspend();
System.out.println("main end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行結果:
卡在數字後面,並沒有列印出main end。
原因是在於println()方法,查看其源碼會更加清晰:
由源碼可以得知,在println內部存在同步鎖,當線程在println()內部停止時,同步鎖就永遠不會釋放,就會導致死鎖。
1.8.3suspend與resume方法的缺點——不同步:
使用這兩個方法容易出現數據不同步的情況。
共用數據類:
public class MyObject {
private String username = "1";
private String password = "11";
public void setValue(String u,String p) {
this.username = u;
if("a".equals(Thread.currentThread().getName())) {
System.out.println("停止a線程");
Thread.currentThread().suspend();
}
this.password = p;
}
public void printUsernamePassword() {
System.out.println(username + "|||" + password);
}
}
執行代碼:
public class Main {
public static void main(String[] args) {
try {
final MyObject object = new MyObject();
Thread thread = new Thread() {
@Override
public void run() {
object.setValue("a","aa");
}
};
thread.setName("a");
thread.start();
Thread.sleep(1000);
Thread thread1 = new Thread() {
@Override
public void run() {
object.printUsernamePassword();
}
};
thread1.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行結果:
源碼地址:https://github.com/lilinzhiyu/threadLearning
本文內容是書中內容兼具自己的個人看法所成。可能在個人看法上會有諸多問題(畢竟知識量有限,導致認知也有限),如果讀者覺得有問題請大膽提出,我們可以相互交流、相互學習,歡迎你們的到來,心成意足,等待您的評價。