前面說到了Java中的同步問題 下面通過一個小小的實(shí)例程序來演示Java中的同步方法 其中對前文提到的Counter類做了稍微的修改
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序設(shè)計(jì)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了張北免費(fèi)建站歡迎大家使用!
public class Counter {
private int c = ;
public void increment() {
System out println( before increment c = + c);
c++;
try {
Thread sleep( );
} catch (InterruptedException e) {
e printStackTrace();
}
System out println( after increment c = + c);
}
public? void decrement() {
System out println( before decrement c = + c);
c ;
try {
Thread sleep( );
} catch (InterruptedException e) {
e printStackTrace();
}
System out println( after decrement c = + c);
}
public int value() {
return c;
}
}
在上面的Counter類的實(shí)現(xiàn)中 分別對increment和decrement方法中增加了sleep( )的調(diào)用 這樣做的目的是為了放大兩個線程對同一對象的方法調(diào)用時的交錯效果
下面是兩個線程 在ThreadA中調(diào)用了 次increment()方法 在ThreadB中調(diào)用了 次decrement()方法
Thread
public class ThreadA implements Runnable {
private Counter c;
public ThreadA(Counter c) {
this c = c;
}
@Override
public void run() {
for (int i = ; i ; i++) {
this c increment();
}
}
}
ThreadB
public class ThreadB implements Runnable {
private Counter c;
public ThreadB(Counter c) {
this c = c;
}
@Override
public void run() {
for (int i = ; i ; i++) {
this c decrement();
}
}
}
主程序如下 其中生成了兩個線程threadA和ThreadB 他們共享Counter c
public class Main {
public static void main(String[] args) {
Counter c = new Counter();
ThreadA a = new ThreadA(c);
ThreadB b = new ThreadB(c);
Thread threadA = new Thread(a);
Thread threadB = new Thread(b);
threadA start();
threadB start();
}
}
執(zhí)行上面的代碼 可能的結(jié)果如下
before increment c =
before decrement c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after increment c =
before increment c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after decrement c =
before decrement c =
after increment c =
before increment c =
after increment c =
before increment c =
after decrement c =
before decrement c =
after increment c =
after decrement c =
before decrement c =
after decrement c =
從上面的輸出結(jié)果中我們不難看出出現(xiàn)了嚴(yán)重的交錯現(xiàn)象! 在increment或者是decrement方法中輸出before和after本應(yīng)該是成對連續(xù)出現(xiàn)的 但輸出結(jié)果卻不是如此
將上面代碼的increment()和decrement()方法用synchronized 修飾后 重新運(yùn)行該程序 輸出結(jié)果如下
before increment c =
after increment c =
before increment c =
after increment c =
before decrement c =
after decrement c =
before increment c =
after increment c =
before decrement c =
after decrement c =
before decrement c =
after decrement c =
before decrement c =
after decrement c =
before decrement c =
after decrement c =
before increment c =
after increment c =
before decrement c =
after decrement c =
before decrement c =
after decrement c =
before decrement c =
after decrement c =
before decrement c =
after decrement c =
before increment c =
after increment c =
before decrement c =
after decrement c =
before increment c =
after increment c =
before increment c =
after increment c =
before increment c =
after increment c =
before increment c =
after increment c =
before increment c =
after increment c =
這樣輸出結(jié)果和沒有增加synchronized修飾符時的大不相同 單獨(dú)一次的increment和decrement方法并沒有出現(xiàn)交錯的現(xiàn)象 只是連續(xù) 次的increment()和decrement ()有交錯(這個不是synchronized能解決的問題)
至少 我們從上面的實(shí)例程序中可以看到synchronized方法的作用了
lishixinzhi/Article/program/Java/hx/201311/26369
1。同步代碼塊:
synchronized(同一個數(shù)據(jù)){} 同一個數(shù)據(jù):就是N條線程同時訪問一個數(shù)據(jù)。
2。
同步方法:
public synchronized 數(shù)據(jù)返回類型 方法名(){}
就
是使用 synchronized 來修飾某個方法,則該方法稱為同步方法。對于同步方法而言,無需顯示指定同步監(jiān)視器,同步方法的同步監(jiān)視器是
this
也就是該對象的本身(這里指的對象本身有點(diǎn)含糊,其實(shí)就是調(diào)用該同步方法的對象)通過使用同步方法,可非常方便的將某類變成線程安全的類,具有如下特征:
1,該類的對象可以被多個線程安全的訪問。
2,每個線程調(diào)用該對象的任意方法之后,都將得到正確的結(jié)果。
3,每個線程調(diào)用該對象的任意方法之后,該對象狀態(tài)依然保持合理狀態(tài)。
注:synchronized關(guān)鍵字可以修飾方法,也可以修飾代碼塊,但不能修飾構(gòu)造器,屬性等。
實(shí)現(xiàn)同步機(jī)制注意以下幾點(diǎn): 安全性高,性能低,在多線程用。性能高,安全性低,在單線程用。
1,不要對線程安全類的所有方法都進(jìn)行同步,只對那些會改變共享資源方法的進(jìn)行同步。
2,如果可變類有兩種運(yùn)行環(huán)境,當(dāng)線程環(huán)境和多線程環(huán)境則應(yīng)該為該可變類提供兩種版本:線程安全版本和線程不安全版本(沒有同步方法和同步塊)。在單線程中環(huán)境中,使用線程不安全版本以保證性能,在多線程中使用線程安全版本.
線程通訊:
為什么要使用線程通訊?
當(dāng)
使用synchronized
來修飾某個共享資源時(分同步代碼塊和同步方法兩種情況),當(dāng)某個線程獲得共享資源的鎖后就可以執(zhí)行相應(yīng)的代碼段,直到該線程運(yùn)行完該代碼段后才釋放對該
共享資源的鎖,讓其他線程有機(jī)會執(zhí)行對該共享資源的修改。當(dāng)某個線程占有某個共享資源的鎖時,如果另外一個線程也想獲得這把鎖運(yùn)行就需要使用wait()
和notify()/notifyAll()方法來進(jìn)行線程通訊了。
Java.lang.object 里的三個方法wait() notify() notifyAll()
wait方法導(dǎo)致當(dāng)前線程等待,直到其他線程調(diào)用同步監(jiān)視器的notify方法或notifyAll方法來喚醒該線程。
wait(mills)方法
都是等待指定時間后自動蘇醒,調(diào)用wait方法的當(dāng)前線程會釋放該同步監(jiān)視器的鎖定,可以不用notify或notifyAll方法把它喚醒。
notify()
喚醒在同步監(jiān)視器上等待的單個線程,如果所有線程都在同步監(jiān)視器上等待,則會選擇喚醒其中一個線程,選擇是任意性的,只有當(dāng)前線程放棄對該同步監(jiān)視器的鎖定后,也就是使用wait方法后,才可以執(zhí)行被喚醒的線程。
notifyAll()方法
喚醒在同步監(jiān)視器上等待的所有的線程。只用當(dāng)前線程放棄對該同步監(jiān)視器的鎖定后,才可以執(zhí)行被喚醒的線程
首先得弄清楚 你的插入是對同一數(shù)據(jù)庫 還是不同數(shù)據(jù)庫的操作數(shù)據(jù)量大的時候 是否要求即時性 是否牽扯到事物
本人推薦 做一個跑批程序 進(jìn)行同步數(shù)據(jù) 這樣能提高代碼性能 以及程序性能 當(dāng)然 你所說的瓶頸 無非就是大數(shù)據(jù)量對數(shù)據(jù)庫的操作次數(shù) 以及海量數(shù)據(jù)造成程序效率的一個瓶頸 謝謝!