今天在Github 看Java synchronized方面的知識總結時
看到一個有趣的說法“子類不能繼承父類的synchronized關鍵字”
我心裏的第一個想法是:爲什麼子類不能繼承父類的synchronized關鍵字呢
於是我決定用代碼實踐一下
首先,我先放上測試類主類的代碼,運行哪個則註釋其餘的代碼:
package com.way.test;
public class Main {
public static void main(String[] args) {
// 注意初始化不能放在for循環中,
//// 因爲synchronized是對象鎖, 鎖的是對象,
//// 如果每次for循環中都新建了一個對象, 那麼這把鎖就毫無意義,怎樣運行都是異步的效果
Father father = new Father();
for (int i =0;i<5;i++) {
new Thread(new Runnable() {
@Override
public void run() {
father.method();
}
}).start();
}
// Son son = new Son();
//
// for (int i =0;i<5;i++) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// son.method();
// }
// }).start();
// }
// SonOverride sonOverride = new SonOverride();
//
// for (int i = 0; i < 5; i++) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// sonOverride.method();
// }
// }).start();
// }
}
}
// 注意初始化不能放在for循環中,
// 因爲synchronized是對象鎖, 鎖的是對象,
// 如果每次for循環中都新建了一個對象, 那麼這把鎖就毫無意義,怎樣運行都是異步的效果
父類的代碼:
package com.way.test;
public class Father{
public synchronized void method(){
System.out.println("AA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("BB");
}
}
中間休眠一秒是爲了有足夠時間觀察方法是否“同步”,否則太快的話是可能看不出來。
運行結果:
可以看出AA——間隔一秒——BB是交替打印
然後,分別寫兩個子類,一個是直接繼承上面的父類
package com.way.test;
public class Son extends Father {
}
運行結果:
可以看出跟父類是一樣的,證明了是繼承了父類的synchronized關鍵字
而另外一個則是繼承並且重寫了父類的方法,注意這裏不要加上synchronized關鍵字
package com.way.test;
public class SonOverride extends Father{
@Override
public void method() {
System.out.println("AAA "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("BBB "+Thread.currentThread().getName());
}
}
運行結果:
很明顯這次運行結果是“異步的”,整個過程只間隔了一秒
倘若,我們在SonOverride中重寫的方法中加上“Synchronized”關鍵字的話
@Override
public synchronized void method() {
那麼運行結果:
可見效果跟直接繼承父類類似。