1.8暂停线程
在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;}@Overridepublic 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() {@Overridepublic void run() {object.printString();}};thread1.setName("a");thread1.start();Thread.sleep(1000);Thread thread2 = new Thread() {@Overridepublic 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;@Overridepublic 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() {@Overridepublic void run() {object.setValue("a","aa");}};thread.setName("a");thread.start();Thread.sleep(1000);Thread thread1 = new Thread() {@Overridepublic void run() {object.printUsernamePassword();}};thread1.start();} catch (InterruptedException e) {e.printStackTrace();}} }執行結果:
?
源碼地址:https://github.com/lilinzhiyu/threadLearning
本文內容是書中內容兼具自己的個人看法所成。可能在個人看法上會有諸多問題(畢竟知識量有限,導致認知也有限),如果讀者覺得有問題請大膽提出,我們可以相互交流、相互學習,歡迎你們的到來,心成意足,等待您的評價。
?
轉載于:https://www.cnblogs.com/lilinzhiyu/p/7986231.html
總結
- 上一篇: go语言入门(三)
- 下一篇: 做梦梦到家人进监狱了是怎么回事