乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      重復(fù)插入數(shù)據(jù)的另類(lèi)解決思路

       WindySky 2018-02-25
                                        在進(jìn)行插入數(shù)據(jù)時(shí),我們會(huì)先從數(shù)據(jù)庫(kù)查詢(xún)是否已經(jīng)擁有該記錄,但是最后會(huì)發(fā)現(xiàn)這個(gè)判斷沒(méi)有任何效果,導(dǎo)致這個(gè)判斷失效的原因有很多,比如事務(wù)沒(méi)有提交,或者多臺(tái)服務(wù)器都執(zhí)行了相同的代碼,或者你的控制器(strut2的Action,springMVC的Controller等)是多實(shí)例的!
          該博客旨在解決最后一種問(wèn)題。
          知識(shí)補(bǔ)充:
          1、SpringMvc的Controller是默認(rèn)是單例的,Struts2的Action是多例的,spring注入默認(rèn)是單例的。
          2、synchronized(this){
                       同步代碼塊
                 }
                a、與放在方法上修飾一樣,都是鎖住的對(duì)象,也就是說(shuō)任何線(xiàn)程執(zhí)行到這里時(shí)都需要獲得該方法的對(duì)象鎖,然后才能執(zhí)行括號(hào)里面的代碼,稱(chēng)為同步(任何時(shí)間都只有一個(gè)線(xiàn)程在執(zhí)行同步代碼塊)。
                b、如果該代碼執(zhí)行時(shí)間特別長(zhǎng),其他線(xiàn)程都在等著代碼執(zhí)行完,就是同步阻塞狀態(tài)。
                c、this也可以替換為其他的對(duì)象,與之類(lèi)似,其他線(xiàn)程到此時(shí),需要獲得該對(duì)象的鎖,才能執(zhí)行同步代碼塊。
                d、特別的,如果方法上有static和synchronized關(guān)鍵字,這時(shí)就變成了類(lèi)鎖,要執(zhí)行同步代碼,各個(gè)線(xiàn)程之間就需要對(duì)類(lèi)鎖競(jìng)爭(zhēng),誰(shuí)有類(lèi)鎖才能夠執(zhí)行。
          3、線(xiàn)程安全指的是多個(gè)線(xiàn)程之間的切換不會(huì)導(dǎo)致程序執(zhí)行完后出現(xiàn)多種結(jié)果。
          
              如果你使用Struts2、spring,你會(huì)發(fā)現(xiàn)這類(lèi)似于多線(xiàn)程,一條請(qǐng)求進(jìn)來(lái)新建一個(gè)Action,然后注入業(yè)務(wù)實(shí)現(xiàn)類(lèi)。同一時(shí)間多個(gè)相同請(qǐng)求并發(fā),就會(huì)有可能繞過(guò)你的重復(fù)判斷,即同一時(shí)間,每個(gè)線(xiàn)程都有可能查詢(xún)不到重復(fù)結(jié)果。
             解決方法:
             1、通常情況下,我們可以給判斷重復(fù)的字段上加上聯(lián)合主鍵來(lái)判斷唯一即可,但是很多時(shí)候我們不愿意這樣做,因?yàn)闀?huì)減少插入的效率。數(shù)據(jù)庫(kù)在每次插入時(shí)都會(huì)遍歷數(shù)據(jù)來(lái)判斷是否唯一,不唯一就拋出異常,在大數(shù)據(jù)量大批量插入時(shí),效率急劇下降。
             2、當(dāng)然你可以直接給你的方法加上synchronized來(lái)鎖住插入方法的對(duì)象,任何人要執(zhí)行插入的操作方法,就必須得到該方法的對(duì)象鎖,但是如果方法特別慢,就會(huì)同步阻塞。

          此時(shí)給出一種思路,用一個(gè)線(xiàn)程安全的標(biāo)識(shí)位來(lái)實(shí)現(xiàn)同步。
          流程:
          1、各個(gè)線(xiàn)程將自己需要修改的資源作為標(biāo)識(shí)位,這里我們將可以用來(lái)判斷重復(fù)的字段值作為標(biāo)志位。
          2、提供一個(gè)全局變量存放這些標(biāo)識(shí)位,對(duì)這個(gè)全局變量的操作必須保證線(xiàn)程安全,即任意時(shí)刻都只能有一個(gè)線(xiàn)程修改、查找這個(gè)全局變量。
          3、每次進(jìn)行插入操作時(shí),先判斷是否全局變量含有自己的標(biāo)識(shí)位。沒(méi)有,放入自己的標(biāo)識(shí)位;有,說(shuō)明在此之前已經(jīng)有其他線(xiàn)程在執(zhí)行這個(gè)方法。
          4、從數(shù)據(jù)庫(kù)里查詢(xún)判斷重復(fù)。
          5、執(zhí)行操作方法。
          6、執(zhí)行完后,釋放掉標(biāo)識(shí)位,告訴其他相同標(biāo)識(shí)位的線(xiàn)程“你可以執(zhí)行了!”,但是具體能不能夠執(zhí)行,也得經(jīng)過(guò)數(shù)據(jù)庫(kù)的重復(fù)判斷。
          

          請(qǐng)看代碼:

      1. public class Cache {  
      2.     private static Map<String, String> map = new ConcurrentHashMap<String, String>();  
      3.   
      4.     private Cache() {  
      5.     }  
      6.   
      7.     public static Map<String,String> getInstance() {  
      8.         return map;  
      9.     }  
      10. }  
      上面是一個(gè)簡(jiǎn)單的單例對(duì)象來(lái)作為全局變量,不同的是這個(gè)單例是一個(gè)Map類(lèi)型的,我們可以存放多個(gè)標(biāo)識(shí)位,這樣不同標(biāo)識(shí)位的線(xiàn)程是可以執(zhí)行的。
      1. private boolean isInCache(String key){  
      2.         synchronized (Cache.getInstance())  
      3.         {  
      4.             if(Cache.getInstance().containsKey(key)){  
      5.                 return true;  
      6.             }else{  
      7.                 Cache.getInstance().put(key, key);  
      8.             }  
      9.         }  
      10.        return false;  
      11. }  
      以上代碼是對(duì)全局變量操作的,讀者可以看到,synchronized可以保證線(xiàn)程安全,而且是對(duì)Map進(jìn)行put和containsKey操作,效率極快,幾乎不會(huì)造成同步阻塞。參數(shù)key是由你自己定義的,合理使用就可以讓有插入相同資源想法的線(xiàn)程們變成同步的。(我這里因?yàn)闃I(yè)務(wù)需求,orgId和classId兩個(gè)都相同說(shuō)明是重復(fù)數(shù)據(jù), 所以我將兩個(gè)值拼接起來(lái)作為標(biāo)志位)
      1. if (!isInCache(orgId + classId)){  
      2.     if('數(shù)據(jù)庫(kù)的重復(fù)判斷'){  
      3.               
      4.     }  
      5. }  
      以上代碼就是對(duì)重復(fù)插入的判斷,外層判斷使線(xiàn)程不重復(fù),內(nèi)層判斷使數(shù)據(jù)不重復(fù)。

      1. synchronized (Cache.getInstance()) {  
      2.     Cache.getInstance().remove(orgId + classId);  
      3. }  
      最后,代碼執(zhí)行完后,請(qǐng)釋放資源,告訴其他相同想法的線(xiàn)程可以進(jìn)來(lái)看一下,但是由于你已經(jīng)執(zhí)行了,數(shù)據(jù)庫(kù)已經(jīng)有值了,內(nèi)層判斷不會(huì)讓它執(zhí)行的。當(dāng)然你也可以不釋放,最后的結(jié)果是Map里面的值越積越多~~


        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多