13、synchronized同步程式碼塊
阿新 • • 發佈:2018-12-22
synchronized同步方法的弊端
當A執行緒呼叫物件中的同步方法時執行任務的時間很長,這樣B執行緒要一直晾著,啥事也幹不了。這就是弊端!
假設A,B,C,D等多位顧客正在超市收銀臺結賬,A正在結賬的時候發現自己錢沒帶,需要回家去拿,剩下的顧客如果一直等著A回家拿完錢結完賬才能買單,那就很耽誤後面顧客的時間。這時候應該讓後面的人結賬走人。
放到執行緒中就是 A執行緒任務花費時間長,應該讓其他執行緒先執行。
package com.demo15; import java.text.SimpleDateFormat; public class MyObject { synchronized public void myTaskA(){ try { System.out.println("myTaskA"); System.out.println("myTaskA即將進入睡眠,時間=" + SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis())); Thread.sleep(5000); System.out.println("myTaskA即將結束睡眠,時間=" + SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis())); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public void myTaskB(){ System.out.println("myTaskB"); } }
package com.demo15;
public class ThreadA extends Thread {
MyObject myObject = new MyObject();
public ThreadA(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
myObject.myTaskA();
}
}
package com.demo15; public class ThreadB extends Thread { MyObject myObject = new MyObject(); public ThreadB(MyObject myObject) { this.myObject = myObject; } @Override public void run() { myObject.myTaskB(); } }
package com.demo15; import java.text.SimpleDateFormat; public class Run { public static String begintime ; public static void main(String[] args) { MyObject myObject = new MyObject(); ThreadA threadA = new ThreadA(myObject); ThreadB threadB = new ThreadB(myObject); threadA.start(); threadB.start(); } }
執行結果:
myTaskA
myTaskA即將進入睡眠,時間=2018-12-11 23:06:21
myTaskA即將結束睡眠,時間=2018-12-11 23:06:26
myTaskB
通過結果可知,A執行同步方法花費了5秒,這期間B什麼也不能做!
作出以下的修改:
package com.demo15;
import java.text.SimpleDateFormat;
public class MyObject {
public void myTaskA(){
try {
synchronized(this){
System.out.println("myTaskA");
}
System.out.println("myTaskA即將進入睡眠,時間=" +
SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
Thread.sleep(5000);
System.out.println("myTaskA即將結束睡眠,時間=" +
SimpleDateFormat.getDateTimeInstance().format(System.currentTimeMillis()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void myTaskB(){
System.out.println("myTaskB");
}
}
此時的執行結果為:
myTaskA
myTaskB
myTaskA即將進入睡眠,時間=2018-12-11 23:20:05
myTaskA即將結束睡眠,時間=2018-12-11 23:20:10
當A執行完同步程式碼塊之後,立即釋放鎖,讓其他執行緒執行!然後再獲取CPU資源來執行後續的花費事件長的任務。
通過上面的例子我們可以看到 使用同步程式碼塊 相對使用同步方法的優勢!