若是 a 和 b 都是對象,則 a==b 是比較兩個對象的引用,只有當 a 和 b 指向的是堆中的同一個對象纔會返回 true,而 a.equals(b) 是進行邏輯比較,當內容相同時,返回true,因此一般須要重寫該方法來提供邏輯一致性的比較。 例如,String 類重寫 equals() 方法,因此能夠用於兩個不一樣對象,可是包含的字母相同的比較。
ArrayList 和Vector他們底層的實現都是同樣的,都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增長和插入元素,它們都容許直接按序號索引元素,可是插入元素要涉及數組元素移動等內存操做,因此索引數據快而插入數據慢。
Vector中的方法因爲添加了synchronized修飾,所以Vector是線程安全的容器,但性能上較ArrayList差,所以已是Java中的遺留容器。
LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元經過附加的引用關聯起來,造成一個能夠按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據須要進行前向或後向遍歷,可是插入數據時只須要記錄本項的先後項便可,因此插入速度較快。
Vector屬於遺留容器(Java早期的版本中提供的容器,除此以外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,可是因爲ArrayList和LinkedListed都是非線程安全的,若是遇到多個線程操做同一個容器的場景,則能夠經過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器後再使用(這是對裝潢模式的應用,將已有對象傳入另外一個類的構造器中建立新的對象來加強實現)。
Overload是重載的意思,
Override是覆蓋的意思,也就是重寫。
重載Overload表示同一個類中能夠有多個名稱相同的方法,但這些方法的參數列表各不相同(即參數個數或類型不一樣)。
重寫Override表示子類中的方法能夠與父類中的某個方法的名稱和參數徹底相同,經過子類建立的實例對象調用這個方法時,將調用子類中的定義方法,這至關於把父類中定義的那個徹底相同的方法給覆蓋了,這也是面向對象編程的多態性的一種表現。
子類覆蓋父類的方法時,只能比父類拋出更少的異常,或者是拋出父類拋出的異常的子異常,由於子類能夠解決父類的一些問題,不能比父類有更多的問題。
子類方法的訪問權限只能比父類的更大,不能更小。
若是父類的方法是private類型,那麼,子類則不存在覆蓋的限制,至關於子類中增長了一個全新的方法。
重載overload的特色就是與返回值無關,只看參數列表,因此重載的方法是能夠改變返回值類型的。因此,若是兩個方法的參數列表徹底同樣,是不能經過讓他們的返回值類型不一樣來實現重載的。咱們能夠用反證法來講明這個問題,由於咱們有時候調用一個方法時也能夠不定義返回結果變量,即不要關心其返回結果,例如,咱們調用map.remove(key)方法時,雖然remove方法有返回值,可是咱們一般都不會定義接收返回結果的變量,這時候假設該類中有兩個名稱和參數列表徹底相同的方法,僅僅是返回類型不一樣,java就沒法肯定編程者倒底是想調用哪一個方法了,由於它沒法經過返回結果類型來判斷。
對於sleep()方法,咱們首先要知道該方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。
sleep()方法致使了程序暫停執行指定的時間,讓出cpu該其餘線程,可是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。
在調用sleep()方法的過程當中,線程不會釋放對象鎖。
而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備
獲取對象鎖進入運行狀態。
轉載自:http://blog.csdn.net/zhandoushi1982/article/details/8745027 在Java 1.2中就引入了java.lang.ref這個包,WeakReference就屬於這個包。WeakReference是幹嗎的呢,一言弊之,它是和Java中的垃圾回收相關的。若是一個對象只有WeakReference引用它,那麼這個對象就可能被垃圾回收器回收。 在什麼場合下應用WeakReference呢? (1) 有時咱們會碰到一些不能繼承的類,如final class,沒法繼承它。假如咱們要使用一個Widget類,由於某種緣故沒法繼承該類來加入某個功能。可是,咱們必須將每一個Widget對象和某個序列號關聯,而Widget自己沒有serial number這個屬性,這時該怎麼作呢? 你也許已經想到,用HashMap:serialNumberMap.put(widget, widgetSerialNumber);這看起來工做的很好。可是有個問題:當咱們再也不須要某個Widget的serial number信息,此時應該從HashMap中將這個Entry移除,若是咱們忘記了怎麼辦?由於HashMap中持有對這個對象的引用,這個對象永遠不會被垃圾回收器回收,這就形成了內存泄漏!這意味着咱們須要像沒有垃圾回收功能的語言同樣,手動管理內存!可是咱們用的是Java。 (2)另外一個很常見的問題是緩存。若是使用強引用,那麼咱們緩存的對象就會一直滯留在內存中,不會被回收,除非咱們手動的將其從緩存中移除。此外,這還須要咱們決定什麼時候從緩存中移除對象,又一個手動管理內存的問題!此時,WeakReference就顯示出它的價值了。如何建立一個WeakReference呢? 要注意的是,當調用weakReference.get()可能返回null(意味着指向的對象已經被回收)。其實,對於Widget serial number這個問題,最簡單的方法是使用WeakHashMap,它的使用和普通的HashMap徹底同樣,不一樣點在於,WeakHashMap的key被實現爲一種WeakReference(注意,是key而不是value),當key對象被回收後,WeakHashMap會自動將對應的entry移除。更精確的說,對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的回收。 (3)Java中有四種類型的引用,按照強弱關係依次爲:Strong Reference>Soft Reference>WeakReference> Phantom Reference。其中,咱們日常用的就是Strong Reference,而Phantom Reference不多用到,那麼什麼是Soft Reference呢? Soft Reference和weak reference的區別是:一旦gc發現對象是weak reference可達就會把它放到ReferenceQueue中,而後等下次gc時回收它;當對象是Soft reference可達時,gc可能會向操做系統申請更多內存,而不是直接回收它,當實在沒轍了纔回收它。像cache系統,最適合用Soft reference。讓gc來替咱們決定何時回收對象以及回收哪些對象。差異樣例以下:WeakReference的模型 A obj = new A(); WeakReference wr = new WeakReference(obj); obj = null; //等待一段時間,obj對象就會被垃圾回收 ... if (wr.get()==null) { System.out.println("obj 已經被清除了 "); } else { System.out.println("obj 還沒有被清除,其信息是 "+obj.toString()); }
詳細轉載https://blog.csdn.net/leonzhang1027/article/details/79480138 咱們經過看JDK源碼來看看爲何SimpleDateFormat和DateFormat類不是線程安全的真正緣由: SimpleDateFormat繼承了DateFormat,在DateFormat中定義了一個protected屬性的 Calendar類的對象:calendar。只是由於Calendar累的概念複雜,牽扯到時區與本地化等等,Jdk的實現中使用了成員變量來傳遞參數,這就形成在多線程的時候會出現錯誤。 calendar.setTime(date)這條語句改變了calendar,稍後,calendar還會用到(在subFormat方法裏),而這就是引起問題的根源。想象一下,在一個多線程環境下,有兩個線程持有了同一個SimpleDateFormat的實例,分別調用format方法: 線程1調用format方法,改變了calendar這個字段。 中斷來了。 線程2開始執行,它也改變了calendar。 又中斷了。 線程1回來了,此時,calendar已然不是它所設的值,而是走上了線程2設計的道路。若是多個線程同時爭搶calendar對象,則會出現各類問題,時間不對,線程掛死等等。 分析一下format的實現,咱們不難發現,用到成員變量calendar,惟一的好處,就是在調用subFormat時,少了一個參數,卻帶來了這許多的問題。其實,只要在這裏用一個局部變量,一路傳遞下去,全部問題都將迎刃而解。 這個問題背後隱藏着一個更爲重要的問題--無狀態:無狀態方法的好處之一,就是它在各類環境下,均可以安全的調用。衡量一個方法是不是有狀態的,就看它是否改動了其它的東西,好比全局變量,好比實例的字段。format方法在運行過程當中改動了SimpleDateFormat的calendar字段,因此,它是有狀態的。 這也同時提醒咱們在開發和設計系統的時候注意下一下三點: 1.本身寫公用類的時候,要對多線程調用狀況下的後果在註釋裏進行明確說明 2.對線程環境下,對每個共享的可變變量都要注意其線程安全性 3.咱們的類和方法在作設計的時候,要儘可能設計成無狀態的 三.解決辦法 1.須要的時候建立新實例: 說明:在須要用到SimpleDateFormat 的地方新建一個實例,無論何時,將有線程安全問題的對象由共享變爲局部私有都能避免多線程問題,不過也加劇了建立對象的負擔。在通常狀況下,這樣其實對性能影響比不是很明顯的。 2.使用同步:同步SimpleDateFormat對象 說明:當線程較多時,當一個線程調用該方法時,其餘想要調用此方法的線程就要block,多線程併發量大的時候會對性能有必定的影響 3.使用ThreadLocal: 說明:使用ThreadLocal, 也是將共享變量變爲獨享,線程獨享確定能比方法獨享在併發環境中能減小很多建立對象的開銷。若是對性能要求比較高的狀況下,通常推薦使用這種方法。 4.拋棄JDK,使用其餘類庫中的時間格式化類: 1.使用Apache commons 裏的FastDateFormat,宣稱是既快又線程安全的SimpleDateFormat, 惋惜它只能對日期進行format, 不能對日期串進行解析。 2.使用Joda-Time類庫來處理時間相關問題 作一個簡單的壓力測試,方法一最慢,方法三最快,可是就算是最慢的方法一性能也不差,通常系統方法一和方法二就能夠知足,因此說在這個點很難成爲你係統的瓶頸所在。從簡單的角度來講,建議使用方法一或者方法二,若是在必要的時候,追求那麼一點性能提高的話,能夠考慮用方法三,用ThreadLocal作緩存。 Joda-Time類庫對時間處理方式比較完美,建議使用。
早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal爲解決多線程程序的併發問題提供了一種新的思路。使用這個工具類能夠很簡潔地編寫出優美的多線程程序。 ThreadLocal,顧名思義,它不是一個線程,而是線程的一個本地化對象。當工做於多線程中的對象使用ThreadLocal維護變量時,ThreadLocal爲每一個使用該變量的線程分配一個獨立的變量副本。因此每個線程均可以獨立地改變本身的副本,而不會影響其餘線程所對應的副本。從線程的角度看,這個變量就像是線程的本地變量,這也是類名中「Local」所要表達的意思。 線程局部變量並非Java的新發明,不少語言(如IBM XL、FORTRAN)在語法層面就提供線程局部變量。在Java中沒有提供語言級支持,而以一種變通的方法,經過ThreadLocal的類提供支持。因此,在Java中編寫線程局部變量的代碼相對來講要笨拙一些,這也是爲何線程局部變量沒有在Java開發者中獲得很好普及的緣由。 學習JDK中的類,首先看下JDK API對此類的描述,描述以下: 該類提供了線程局部 (thread-local) 變量。這些變量不一樣於它們的普通對應物,由於訪問某個變量(經過其 get 或 set 方法)的每一個線程都有本身的局部變量,它獨立於變量的初始化副本。ThreadLocal 實例一般是類中的 private static 字段,它們但願將狀態與某一個線程(例如,用戶 ID 或事務 ID)相關聯。 API表達了下面幾種觀點: 1、ThreadLocal不是線程,是線程的一個變量,你能夠先簡單理解爲線程類的屬性變量。 2、ThreadLocal在類中一般定義爲靜態變量。 3、每一個線程有本身的一個ThreadLocal,它是變量的一個「拷貝」,修改它不影響其餘線程。 既然定義爲類變量,爲什麼爲每一個線程維護一個副本(姑且稱爲「拷貝」容易理解),讓每一個線程獨立訪問?多線程編程的經驗告訴咱們,對於線程共享資源(你能夠理解爲屬性),資源是否被全部線程共享,也就是說這個資源被一個線程修改是否影響另外一個線程的運行,若是影響咱們須要使用synchronized同步,讓線程順序訪問。 ThreadLocal適用於資源共享但不須要維護狀態的狀況,也就是一個線程對資源的修改,不影響另外一個線程的運行;這種設計是‘空間換時間’,synchronized順序執行是‘時間換取空間’。
java虛擬機(JVM) 使用java編程語言的主要優點就是平臺的獨立性。你曾經想知道過java怎麼實現平臺的獨立性嗎?對,就是虛擬機,它抽象化了硬件設備,開發者和他們的程序的得以操做系統。虛擬機的職責就是處理和操做系統的交流。java不一樣的接口規範對任何平臺都有良好的支持,由於jvm很好的實現了每一個平臺的規範。jvm能夠理解僞代碼字節碼,在用戶和操做系統之間創建了一層樞紐。 java運行時環境(JRE) java運行時環境是JVM的一個超集。JVM對於一個平臺或者操做系統是明確的,而JRE確實一個通常的概念,他表明了完整的運行時環境。咱們在jre文件夾中看到的全部的jar文件和可執行文件都會變成運行時的一部分。事實上,運行時JRE變成了JVM。因此對於通常狀況時候使用JRE,對於明確的操做系統來講使用JVM。當你下載了JRE的時候,也就自動下載了JVM。 java開發工具箱(JDK) java開發工具箱指的是編寫一個java應用所須要的全部jar文件和可執行文件。事實上,JRE是JDK的一部分。若是你下載了JDK,你會看到一個名叫JRE的文件夾在裏面。JDK中要被牢記的jar文件就是tools.jar,它包含了用於執行java文檔的類還有用於類簽名的jar包。 即時編譯器(JIT) 即時編譯器是種特殊的編譯器,它經過有效的把字節碼變成機器碼來提升JVM的效率。JIT這種功效很特殊,由於他把檢測到的類似的字節碼編譯成單一運行的機器碼,從而節省了CPU的使用。這和其餘的字節碼編譯器不一樣,由於他是運行時(第一類執行的編譯?)the firs of its kind to perform the compilation(從字節碼到機器碼)而不是在程序運行以前。正是由於這些,動態編譯這個詞彙才和JIT有那麼緊密的關係。 轉載:https://www.cnblogs.com/xiaozhijing/p/7919455.html
1,設計模式是爲了解決現實的問題,是對某種問題的解決方案。 2,「對變化點的封裝」出現的不少,我認爲,這點是程序能夠進行擴展的編程方法。這個應該是開閉原則要達到的目標。 3,編程原則是「道」,設計模式是「術」,使用模式的時候,必定要始終貫徹原則。 4,設計模式是基於面向對象的語言,尤爲是繼承,而且用多態的方式來保證程序增長功能,不用修改原代碼。(面向過程不知道能不能實現) 5,代碼的可擴展性,我以爲主要就是開閉原則所帶來的效果, 6,設計模式雖說是模式,可是代碼的實現方法其實很靈活,他對應的應該是一種問題,或者說是如何封裝變化點,具體的封裝方法實現起來比較靈活。 7,程序常常會有不少須要改變的地方,到底需不須要封裝變化點,根本的原則在什麼地方? 下面說說我對幾個模式的認識, 1,簡單工廠模式,解決的是客戶端經過大量的判斷來選擇相應的對象,須要進行封裝的問題。特色是判斷的條件須要統一,好比字符串,或者一個特定的值。使用的結果就是判斷由工廠方法來作。而且能夠經過繼承和多態,使得相同的語句返回一系列擁有共同父類的對象。 2,策略模式,解決的是客戶端選擇方法的封裝方法(與之相比的是簡單工廠模式封裝的是對象),其實把簡單工廠模式稍做修改,就是策略模式了。能夠認爲是用簡單工廠模式返回了一系列有共同父類或者同一接口的對象,而後調用對象的接口或者虛方法。這樣客戶端代碼只是經過工廠生成了一個對象,而後調用對象的方法,並經過多態來實現不一樣的程序功能。 3,裝飾模式,解決的問題是,如今有一個對象,咱們想給他增長方法或者屬性,怎麼去作,而且能夠隨意修改增長方法和屬性的順序。其實我首先想到的是c#的擴展方法。感受和擴展方法的目的差很少。 4,工廠模式,,,正在看。怎麼看怎麼以爲好像在作無用功。。。。。不知道他是幹嗎的。 結合我如今的工做,我最近在作網頁處理程序,ashx。 我就在想這種處理程序,處理網絡請求,我如今用的基本都是面向過程的,就是判斷傳過來什麼方法,執行什麼操做。用switch來跳轉。 如今我有幾個疑問: 1,這種很符合策略模式,我如今要不要使用策略模式?爲何? 2,是否是永遠都要等到問題出現了,纔去引用設計模式? 3,當問題出現的時候,可能須要修改的地方就已經不少了,這時候怎麼辦?
用隱藏表單域,即在b.jsp頁面中用n個hidden把上一頁面提交過來的信息保存下來,而後和當前一塊兒提交,再到c.jsp裏面獲取
說明:儘可能不要用session和少用session
詳細轉載:https://blog.csdn.net/yujin753/article/details/42242297 傳播行爲: Required:默認的事務傳播行爲,表示必須有邏輯事務,不然新建一個事務,使用PROPAGATION_REQUIRED指定,表示若是當前存在一個邏輯事務,則加入該邏輯事務,不然將新建一個邏輯事務 RequiresNew:建立新的邏輯事務,使用 PROPAGATION_REQUIRES_NEW指定,表示每次都建立新的邏輯事務(物理事務也是不一樣的)所以外部事務能夠不受內部事務回滾狀態的影響獨立提交或者回滾。 Supports:支持當前事務,使用PROPAGATION_SUPPORTS指定,指若是當前存在邏輯事務,就加入到該邏輯事務,若是當前沒有邏輯事務,就以非事務方式執行。 NotSupported:不支持事務,若是當前存在事務則暫停該事務,使用PROPAGATION_NOT_SUPPORTED指定,即以非事務方式執行,若是當前存在邏輯事務,就把當前事務暫停,以非事務方式執行。 Mandatory:使用PROPAGATION_MANDATORY指定,若是當前有事務,使用當前事務執行,若是當前沒有事務,則拋出異常(IllegalTransactionStateException)。 Never:不支持事務,若是當前存在是事務則拋出IllegalTransactionStateException異常,使用PROPAGATION_NEVER指定。 Nested:嵌套事務支持,使用PROPAGATION_NESTED指定,若是當前存在事務,則在嵌套事務內執行,若是當前不存在事務,則建立一個新的事務,嵌套事務使用數據庫中的保存點來實現,即嵌套事務回滾不影響外部事務,但外部事務回滾將致使嵌套事務回滾。 Nested和RequiresNew的區別: RequiresNew每次都建立新的獨立的物理事務,而Nested只有一個物理事務; Nested嵌套事務回滾或提交不會致使外部事務回滾或提交,但外部事務回滾將致使嵌套事務回滾,而 RequiresNew因爲都是全新的事務,因此之間是無關聯的; Nested使用JDBC 3的保存點實現,即若是使用低版本驅動將致使不支持嵌套事務。 實際應用中通常使用默認的事務傳播行爲,偶爾會用到RequiresNew和Nested方式。 隔離級別: 1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別. 另外四個與JDBC的隔離級別相對應 2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務能夠看到這個事務未提交的數據。 這種隔離級別會產生髒讀,不可重複讀和幻像讀。 3. ISOLATION_READ_COMMITTED: 保證一個事務修改的數據提交後才能被另一個事務讀取。另一個事務不能讀取該事務未提交的數據 4. ISOLATION_REPEATABLE_READ: 這種事務隔離級別能夠防止髒讀,不可重複讀。可是可能出現幻像讀。 它除了保證一個事務不能讀取另外一個事務未提交的數據外,還保證了避免下面的狀況產生(不可重複讀)。 5. ISOLATION_SERIALIZABLE 這是花費最高代價可是最可靠的事務隔離級別。事務被處理爲順序執行。 除了防止髒讀,不可重複讀外,還避免了幻像讀。
詳細轉載:https://blog.csdn.net/tiedao123456789/article/details/9222475 Memcached的工做原理 Memcached處理的原子是每個(key,value)對(如下簡稱kv對),key會經過一個hash算法轉化成hash-key,便於查找、對比以及作到儘量的散列。同時,memcached用的是一個二級散列,經過一張大hash表來維護。 Memcached有兩個核心組件組成:服務器端(server)和客戶端(client),在一個memcached的查詢中,client先經過計算key的hash值來肯定kv對所處在的server位置。當server肯定後,客戶端就會發送一個查詢請求給對應的server,讓它來查找確切的數據。由於這之間沒有交互以及多播協議,因此memcached交互帶給網絡的影響是最小化的。 舉例說明:考慮如下這個場景,有三個client分別是c1,c2,c3,還有三個ms分別是s1,s2,s3: 設置kv對 c1想設置key=」com」,value=」iQiyi」 c1拿到server列表,並對key作hash轉化,根據hash值肯定kv對所存的server位置 s2被選中了 c1鏈接上s2,s2收到請求,把(key=」com」,value=」iQiyi」)存了起來 獲取kv對 c3想獲得key=」com」的value c3用相同的hash算法算出hash值,並肯定key=」aa」的值存在s2上 c3鏈接上s2,並從s2那邊獲得value=」iQiyi」 其餘任何從c1,c2,c3的想獲得key=」com」的值的請求都會發向s2
數據中的鎖分爲兩類:悲觀鎖和樂觀鎖,鎖還有表級鎖、行級鎖 表級鎖例如: SELECT * FROM table WITH (HOLDLOCK) 其餘事務能夠讀取表,但不能更新刪除 SELECT * FROM table WITH (TABLOCKX) 其餘事務不能讀取表,更新和刪除 行級鎖例如: select * from table_name where id = 1 for update; 悲觀鎖(Pressimistic Locking) 對數據被外界(包括本系統當前的其餘事務,以及來自 外部系統的事務處理)修改持保守態度,所以,在整個數據處理過程當中,將數據處於鎖定狀態。悲觀鎖的實現,每每依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,不然,即便在本系統中實現了加鎖機制,也沒法保證外部系 統不會修改數據)。例如: select * from table_name where id = ‘xxx’ for update; 這樣查詢出來的這一行數據就被鎖定了,在這個update事務提交以前其餘外界是不能修改這條數據的,可是這種處理方式效率比較低,通常不推薦使用。 樂觀鎖(Optimistic Locking) 相對悲觀鎖而言,樂觀鎖機制採起了更加寬鬆的加鎖機制。悲觀鎖大多數狀況下依靠數據庫的鎖機制實現,以保證操做最大程度的獨佔性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷每每沒法承受。如一個金融系統,當某個操做員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶賬戶餘額),若是採用悲觀鎖機制,也就意味着整個操做過程當中(從操做員讀出數據、開始修改直至提交修改結果的全過程,甚至還包括操做員中途去煮咖啡的時間),數據庫記錄始終處於加鎖狀態,能夠想見,若是面對幾百上千個併發,這樣的狀況將致使怎樣的後果。 樂觀鎖機制在必定程度上解決了這個問題。樂觀鎖,大可能是基於數據版本( Version )記錄機制實現。何謂數據版本?即爲數據增長一個版本標識,在基於數據庫表的版本解決方案中,通常是經過爲數據庫表增長一個 「version」 字段來實現。讀取出數據時,將此版本號一同讀出,以後更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,若是提交的數據版本號大於數據庫表當前版本號,則予以更新,不然認爲是過時數據。 舉個樂觀鎖的例子(數據庫version默認爲0): 不如如今一件衣服就剩一個庫存了,可是有兩個用戶同時下單,若是這時候不加以控制很容易出現庫存賣超的狀況,這時候咱們能夠這樣操做: 第一個用戶將這件衣服讀出(version=0),並將庫存-1, 第二個用戶也將這件衣服讀出(version=0),並將庫存-1, 第一個個用戶完成操做,將數據庫版本version+1,執行更新庫存時因爲提交的數據版本大於數據庫記錄的版本,數據被更新,數據庫中的version被更新爲2。 update goods set store=store-1,version=version+1 where id=xx and version=orginal_version 第二個用戶也完成了操做,也將版本version+1,執行更新庫存時發現執行版本和數據庫記錄的版本相同,不符合提交版本必須大於數據庫記錄版本的樂觀鎖策略,因此第二個用戶的下單請求被駁回,咱們能夠經過人性化處理異常給用戶提示該商品已售罄等。 樂觀鎖機制避免了長事務中的數據庫加鎖開銷(兩個用戶操做過程當中,都沒有對數據庫數據加鎖),大大提高了大併發量下的系統總體性能表現。 悲觀鎖:交給數據庫來處理的,由事務(分隱私和顯式事務,平時單條SQL語句就是一個隱式事務)+鎖 那控制的,其中事務至關於鎖的做用域,根據事務的提交失敗或回滾來釋放掉顯式事務中開啓的鎖。(事前處理) 樂觀鎖:是認爲版本號來控制的,這種機制併發性和性能更好(過後處理)
詳細轉載:https://blog.csdn.net/bravekingzhang/article/details/19081467 1. 爲查詢緩存優化你的查詢 2. EXPLAIN 你的 SELECT 查詢 3. 當只要一行數據時使用 LIMIT 1 4. 爲搜索字段建索引 5. 在Join表的時候使用至關類型的例,並將其索引 6. 千萬不要 ORDER BY RAND() 7. 避免 SELECT * 8. 永遠爲每張表設置一個ID 9. 使用 ENUM 而不是 VARCHAR 10. 從 PROCEDURE ANALYSE() 取得建議 11. 儘量的使用 NOT NULL 12. Prepared Statements 13. 無緩衝的查詢 14. 把IP地址存成 UNSIGNED INT 15. 固定長度的表會更快 16. 垂直分割 17. 拆分大的 DELETE 或 INSERT 語句 18. 越小的列會越快 19. 選擇正確的存儲引擎 20. 使用一個對象關係映射器(Object Relational Mapper) 21. 當心「永久連接」
1、Session Replication 方式管理 (即session複製)
簡介:將一臺機器上的Session數據廣播複製到集羣中其他機器上
使用場景:機器較少,網絡流量較小
優勢:實現簡單、配置較少、當網絡中有機器Down掉時不影響用戶訪問
缺點:廣播式複製到其他機器有必定廷時,帶來必定網絡開銷
2、Session Sticky 方式管理
簡介:即粘性Session、當用戶訪問集羣中某臺機器後,強制指定後續全部請求均落到此機器上
使用場景:機器數適中、對穩定性要求不是很是苛刻
優勢:實現簡單、配置方便、沒有額外網絡開銷
缺點:網絡中有機器Down掉時、用戶Session會丟失、容易形成單點故障
3、緩存集中式管理
簡介:將Session存入分佈式緩存集羣中的某臺機器上,當用戶訪問不一樣節點時先從緩存中拿Session信息
使用場景:集羣中機器數多、網絡環境複雜
優勢:可靠性好
缺點:實現複雜、穩定性依賴於緩存的穩定性、Session信息放入緩存時要有合理的策略寫入
類加載是一個將類合併到正在運行着的JVM進程中的過程。首先要加載一個類,咱們必須先得將類文件加載進來並鏈接,而且要加上大量的驗證,隨後會生成一個表明着這個類的class對象,而後就能夠經過它去建立新的實例了。
這就是我所理解的Java的類加載機制。
通過加載和鏈接後出來的class對象,說明這個類已經被加載到了JVM中,此後就不會再加載了。