版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1基礎篇1.1基本功1.1.1面向對象特征封裝,繼承,多態(tài)和抽象1、 封裝封裝給對象提供了隱藏內部特性和行為的能力。對象提供一些能被其他對象訪問的方法來改變它內部的數據。在Java當中,有3種修飾符:public,private和protected。每一種修飾符給其他的位于同一個包或者不同包下面對象賦予了不同的訪問權限。下面列出了使用封裝的一些好處:1) 通過隱藏對象的屬性來保護對象內部的狀態(tài)。2) 提高了代碼的可用性和可維護性,因為對象的行為可以被單獨的改變或者是擴展。3) 禁止對象之間的不良交互提高模塊化2、 繼承繼承給對象提供了從基類獲取字段和方法的能力。繼承提供了代碼的重用行,也可以在不修改類的情況下給現存的類添加新特性。3、 多態(tài)多態(tài)是編程語言給不同的底層數據類型做相同的接口展示的一種能力。一個多態(tài)類型上的操作可以應用到其他類型的值上面。4、 抽象抽象是把想法從具體的實例中分離出來的步驟,因此,要根據他們的功能而不是實現細節(jié)來創(chuàng)建類。Java支持創(chuàng)建只暴漏接口而不包含方法實現的抽象的類。這種抽象技術的主要目的是把類的行為和實現細節(jié)分離開。final,finallR,finalize的區(qū)別1、 final修飾符(關鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載。2、 finallR在異常處理時提供finallR塊來執(zhí)行任何清除操作。如果拋出一個異常,那么相匹配的catch子句就會執(zhí)行,然后控制就會進入finallR塊(如果有的話)。3、 finalize方法名。Java技術允許使用finalize()方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在Object類中定義的,因此所有的類都繼承了它。子類覆蓋finalize()方法以整理系統(tǒng)資源或者執(zhí)行其他清理工作。finalize()方法是在垃圾收集器刪除對象之前對這個對象調用的。int和Integer有什么區(qū)別int是基本數據類型,而Integer是其包裝類,注意是一個類。為什么要提供包裝類呢???一是為了在各種類型間轉化,通過各種方法的調用。否則你無法直接通過變量轉化。1.1.4重載和重寫的區(qū)別override(重寫)方法名、參數、返回值相同。子類方法不能縮小父類方法的訪問權限。子類方法不能拋出比父類方法更多的異常(但子類方法可以不拋出異常)。存在于父類和子類之間。方法被定義為final不能被重寫。overload(重載)參數類型、個數、順序至少有一個不相同。不能重載只有返回值不同的方法名。存在于父類和子類、同類中。區(qū)別點重載重寫(覆寫)英文OverloadingOveriding定義方法名稱相同,參數的類型或個數不同方法名稱、參數類型、返回值類型全部相同權限對權限沒要求被重寫的方法不能擁有更嚴格的權限范圍發(fā)生在一個類中發(fā)生在繼承類中1.1.5抽象類和接口有什么區(qū)別接口是公開的,里面不能有私有的方法或變量,是用于讓別人使用的,而抽象類是可以有私有方法或私有變量的,另外,實現接口的一定要實現接口里定義的所有方法,而實現抽象類可以有選擇地重寫需要用到的方法,一般的應用里,最頂級的是接口,然后是抽象類實現接口,最后才到具體類實現。還有,接口可以實現多重繼承,而一個類只能繼承一個超類,但可以通過繼承多個接口實現多重繼承,接口還有標識(里面沒有任何方法,如Remote接口)和數據共享(里面的變量全是常量)的作用。1.1.6說說反射的用途及實現Java反射機制主要提供了以下功能:在運行時構造一個類的對象;判斷一個類所具有的成員變量和方法;調用一個對象的方法;生成動態(tài)代理。反射最大的應用就是框架Java反射的主要功能:-確定一個對象的類-取出類的modifiers,數據成員,方法,構造器,和超類.-找出某個接口里定義的常量和方法說明.-創(chuàng)建一個類實例,這個實例在運行時刻才有名字(運行時間才生成的對象).-取得和設定對象數據成員的值,如果數據成員名是運行時刻確定的也能做到.-在運行時刻調用動態(tài)對象的方法.-創(chuàng)建數組,數組大小和類型在運行時刻才確定,也能更改數組成員的值.反射的應用很多,很多框架都有用到spring的ioc/di也是反射….javaBean和jsp之間調用也是反射….struts的FormBean和頁面之間…也是通過反射調用….JDBC的classForName()也是反射???..hibernate的find(Classclazz)也是反射….反射還有一個不得不說的問題,就是性能問題,大量使用反射系統(tǒng)性能大打折扣。怎么使用使你的系統(tǒng)達到最優(yōu)就看你系統(tǒng)架構和綜合使用問題啦,這里就不多說了。來源:http://uule.iteR/blog/14235121.1.7說說自定義注解的場景及實現登陸、權限攔截、日志處理,以及各種Java框架,如Spring,Hibernate,JUnit提到注解就不能不說反射,Java自定義注解是通過運行時靠反射獲取注解。實際開發(fā)中,例如我們要獲取某個方法的調用日志,可以通過AOP(動態(tài)代理機制)給方法添加切面,通過反射來獲取方法包含的注解,如果包含日志注解,就進行日志記錄。HTTP請求的GET與POST方式的區(qū)別1、 請求數據的方式GET請求,請求的數據會附加在URL之后,以?分割URL和傳輸數據,多個參數用&連接URL的編碼格式采用的是ASCII編碼,而不是uniclde,即是說所有的非ASCII字符都要編碼之后再傳輸。POST請求會把請求的數據放置在HTTP請求包的包體中。因此,GET請求的數據會暴露在地址欄中,而POST請求則不會。2、 傳輸數據的大小在HTTP規(guī)范中,沒有對URL的長度和傳輸的數據大小進行限制。但是在實際開發(fā)過程中,對于GET,特定的瀏覽器和服務器對URL的長度有限制。因此,在使用GET請求時,傳輸數據會受到URL長度的限制。對于POST,由于不是URL傳值,理論上是不會受限制的,但是實際上各個服務器會規(guī)定對POST提交數據大小進行限制,Apache、IIS都有各自的配置。3、 安全性POST的安全性比GET的高。這里的安全是指真正的安全,而不同于上面GET提到的安全方法中的安全,上面提到的安全僅僅是不修改服務器的數據。比如,在進行登錄操作,通過GET請求,用戶名和密碼都會暴露再URL上,因為登錄頁面有可能被瀏覽器緩存以及其他人查看瀏覽器的歷史記錄的原因,此時的用戶名和密碼就很容易被他人拿到了。除此之外,GET請求提交的數據還可能會造成Cross-siterequestfrogerR攻擊4、 HTTP中的GET,POST,SOAP協(xié)議都是在HTTP上運行的參考:blogs.Com/wangli-66/p/5453507.htmlSession與Cookie區(qū)別cookie是Web服務器發(fā)送給瀏覽器的一塊信息。瀏覽器會在本地文件中給每一個Web服務器存儲cookie。以后瀏覽器在給特定的Web服務器發(fā)請求的時候,同時會發(fā)送所有為該服務器存儲的cookie。下面列出了session和cookie的區(qū)別:無論客戶端瀏覽器做怎么樣的設置,session都應該能正常工作??蛻舳丝梢赃x擇禁用cookie,但是,session仍然是能夠工作的,因為客戶端無法禁用服務端的session。JDBC流程1、 加載JDBC驅動程序:在連接數據庫之前,首先要加載想要連接的數據庫的驅動到JVM(Java虛擬機),這通過java.lang.Class類的靜態(tài)方法forName(StringclassName)實現。例如://加載MRSql的驅動類Class.forName(〃com.mRsql.jdbc.Driver〃);成功加載后,會將Driver類的實例注冊到DriverManager類中。2、 提供JDBC連接的URL-連接URL定義了連接數據庫時的協(xié)議、子協(xié)議、數據源標識。-書寫形式:協(xié)議:子協(xié)議:數據源標識協(xié)議:在JDBC中總是以jdbc開始子協(xié)議:是橋連接的驅動程序或是數據庫管理系統(tǒng)名稱。數據源標識:標記找到數據庫來源的地址與連接端口。例如://MRSql的連接URL,true表示使用Unicode字符集,characterEncoding字符編碼方式。jdbc:mRsql://localhost:3306/test?useUnicode=true&characterEncoding=gbk;3、 創(chuàng)建數據庫的連接-要連接數據庫,需要向java.sql.DriverManager請求并獲得Connection對象,該對象就代表一個數據庫的連接。-使用DriverManager的getConnectin(Stringurl,Stringusername,Stringpassword)方法傳入指定的欲連接的數據庫的路徑、數據庫的用戶名和密碼來獲得。例如://連接MRSql數據庫,用戶名和密碼都是rootStringurl=〃jdbc:mRsql://localhost:3306/test〃;Connectioncon=DriverManager.getConnection(url,〃root〃,〃root〃)4、 創(chuàng)建一個Statement,要執(zhí)行SQL語句,必須獲得java.sql.Statement實例,Statement實例分為以下3種類型:執(zhí)行靜態(tài)SQL語句。通常通過Statement實例實現。Statementstmt=con.createStatement();執(zhí)行動態(tài)SQL語句。通常通過PreparedStatement實例實現。PreparedStatementpstmt=con.prepareStatement(sql);執(zhí)行數據庫存儲過程。通常通過CallableStatement實例實現。CallableStatementcstmt=con.prepareCall("{CALLdemoSp(?,?)}”);5、 執(zhí)行SQL語句提供了三種執(zhí)行SQL語句的方法:eRecuteQuerR、eRecuteUpdate和eRecuteResultSeteRecuteQuerR(StringsqlString):執(zhí)行查詢數據庫的SQL語句,返回一個結果集(ResultSet)對象。inteRecuteUpdate(StringsqlString):用于執(zhí)行INSERT、UPDATE或DELETE語句以及SQLDDL語句,如:CREATETABLE和DROPTABLE等eRecute(sqlString):用于執(zhí)行返回多個結果集、多個更新計數或二者組合的語句。6、 處理結果:執(zhí)行更新返回的是本次操作影響到的記錄數。執(zhí)行查詢返回的結果是一個ResultSet對象。-ResultSet包含符合SQL語句中條件的所有行,并且它通過一套get方法提供了對這些行中數據的訪問(列是從左到右編號的,并且從列1開始)。?使用結果集(ResultSet)對象的訪問方法獲取數據:while(rs.neRt()){Stringname=rs.getString("name”);Stringpass=rs.getString(1);//此方法比較高效}7、 關閉JDBC對象操作完成以后要把所有使用的JDBC對象全都關閉,以釋放JDBC資源,關閉順序和聲明順序相反:關閉記錄集rs.close()關閉聲明stmt.close()關閉連接對象conn.close()MVC設計思想M:Model模型V:View視圖C:Controller控制器模型就是封裝業(yè)務邏輯和數據的一個一個的模塊,控制器就是調用這些模塊的(java中通常是用Servlet來實現,框架的話很多是用Struts2來實現這一層),視圖就主要是你看到的,比如JSP等。當用戶發(fā)出請求的時候,控制器根據請求來選擇要處理的業(yè)務邏輯和要選擇的數據,再返回去把結果輸出到視圖層,這里可能是進行重定向或轉發(fā)等.equals與==的區(qū)別值類型(int,char,long,boolean等)都是用==判斷相等性對象引用的話,==判斷引用所指的對象是否是同一個。equals是Object的成員函數,有些類會覆蓋(override)這個方法,用于判斷對象的等價性。例如String類,兩個引用所指向的String都是”abc”,但可能出現他們實際對應的對象并不是同一個(和jvm實現方式有關),因此用==判斷他們可能不相等,但用equals判斷一定是相等的。1.2集合List和Set區(qū)別List,Set都是繼承自Collection接口List特點:元素有放入順序,元素可重復Set特點:元素無放入順序,元素不可重復,重復元素會覆蓋掉(注意:元素雖然無放入順序,但是元素在set中的位置是有該元素的HashCode決定的,其位置其實是固定的,加入Set的Object必須定義equals()方法,另外list支持for循環(huán),也就是通過下標來遍歷,也可以用迭代器,但let只能用迭代,因為他無序,無法用下標來取得想要的值。)Set和List對比:Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引起元素位置改變。List:和數組類似,List可以動態(tài)增長,查找元素效率高,插入刪除元素效率低,因為會引起其他元素位置改變。List和Map區(qū)別List是對象集合,允許對象重復。Map是鍵值對的集合,不允許keR重復。ArraRlist與LinkedList區(qū)別ArraRlist:優(yōu)點:ArraRList是實現了基于動態(tài)數組的數據結構,因為地址連續(xù),一旦數據存儲好了,查詢操作效率會比較高(在內存里是連著放的)。缺點:因為地址連續(xù),ArraRList要移動數據,所以插入和刪除操作效率比較低。LinkedList:優(yōu)點:LinkedList基于鏈表的數據結構,地址是任意的,所以在開辟內存空間的時候不需要等一個連續(xù)的地址,對于新增和刪除操作add和remove,LinedList比較占優(yōu)勢°LinkedList適用于要頭尾操作或插入指定位置的場景缺點:因為LinkedList要移動指針,所以查詢操作性能比較低。適用場景分析:當需要對數據進行對此訪問的情況下選用ArraRList,當需要對數據進行多次增加刪除修改時采用LinkedListoArraRList與Vector區(qū)別//構造一個初始容量為10的空列表publicArraRList()〃構造一個具有指定初始容量的空列表。publicArraRList(intinitialCapacitR)//構造一個包含指定collection的元素的列表publicArraRList(Collection<?eRtendsE>c)Vector有四個構造方法:〃使用指定的初始容量和等于零的容量增量構造一個空向量publicVector()〃構造一個空向量,使其內部數據數組的大小,其標準容量增量為零publicVector(intinitialCapacitR)//構造一個包含指定collection中的元素的向量publicVector(Collection<?eRtendsE>c)//使用指定的初始容量和容量增量構造一個空的向量publicVector(intinitialCapacitR,intcapacitRIncrement)ArraRList和Vector都是用數組實現的,主要有這么三個區(qū)別:Vector是多線程安全的,線程安全就是說多線程訪問同一代碼,不會產生不確定的結果。而ArraRList不是,這個可以從源碼中看出,Vector類中的方法很多有sRnchronized進行修飾,這樣就導致了Vector在效率上無法與ArraRList相比;兩個都是采用的線性連續(xù)空間存儲元素,但是當空間不足的時候,兩個類的增加方式是不同。Vector可以設置增長因子,而ArraRList不可以。Vector是一種老的動態(tài)數組,是線程同步的,效率很低,一般不贊成使用。適用場景分析:Vector是線程同步的,所以它也是線程安全的,而ArraRList是線程異步的,是不安全的如果不考慮到線程的安全因素,一般用ArraRList效率比較高。如果集合中的元素的數目大于目前集合數組的長度時,在集合中使用數據量比較大的數據,用Vector有一定的優(yōu)勢。HashMap和Hashtable的區(qū)別hashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKeR()方法。hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高hashMap允許空鍵值,而hashTable不允許。注意:TreeMap:非線程安全基于紅黑樹實現。TreeMap沒有調優(yōu)選項,因為該樹總處于平衡狀態(tài)。Treemap:適用于按自然順序或自定義順序遍歷鍵(keR)。參考:/qq_22118507/article/details/51576319HashSet和HashMap區(qū)別set是線性結構,set中的值不能重復,hashset是set的hash實現,hashset中值不能重復是用hashmap的keR來實現的。map是鍵值對映射,可以空鍵空值。HashMap是Map接口的hash實現,keR的唯一性是通過keR值hash值的唯一來確定,value值是則是鏈表結構。他們的共同點都是hash算法實現的唯一性,他們都不能持有基本類型,只能持有對象HashMap和ConcurrentHashMap的區(qū)別ConcurrentHashMap是線程安全的HashMap的實現。ConcurrentHashMap對整個桶數組進行了分割分段(Segment),然后在每一個分段上都用lock鎖進行保護,相對于HashTable的sRn關鍵字鎖的粒度更精細了一些,并發(fā)性能更好,而HashMap沒有鎖機制,不是線程安全的。HashMap的鍵值對允許有null,但是ConCurrentHashMap都不允許HashMap的工作原理及代碼實現簡單地說,HashMap在底層將keR-value當成一個整體進行處理,這個整體就是一個EntrR對象。HashMap底層采用一個EntrR口數組來保存所有的keR-value對,當需要存儲一個EntrR對象時,會根據hash算法來決定其在數組中的存儲位置,在根據equals方法決定其在該數組位置上的鏈表中的存儲位置;當需要取出一個EntrR時,也會根據hash算法找到其在數組中的存儲位置,再根據equals方法從該位置上的鏈表中取出該EntrR。Fail-Fast機制是java集合(Collection)中的一種錯誤機制。當多個線程對同一個集合的內容進行操作時,就可能會產生fail-fast事件。例如:當某一個線程A通過iterator去遍歷某集合的過程中,若該集合的內容被其他線程所改變了;那么線程A訪問集合時,就會拋出ConcurrentModificationERception異常,產生fail-fast事件。參考:https://tracRlihui.github.io/2015/07/01/Java集合學習1:HashMap的實現原理ConcurrentHashMap的工作原理及代碼實現HashTable里使用的是sRnchronized關鍵字,這其實是對對象加鎖,鎖住的都是對象整體,當Hashtable的大小增加到一定的時候,性能會急劇下降,因為迭代時需要被鎖定很長的時間。ConcurrentHashMap算是對上述問題的優(yōu)化,其構造函數如下,默認傳入的是16,0.75,16。publicConcurrentHashMap(intpublicConcurrentHashMap(intinitialcapacity,floatloadFactor,intconcurrencyLevel)floatloadFactor,intconcurrencyLevel)(if(!(loadFactor>0)||initialcapacity<0IIconcurrencyLevelthrownewIllegalArgumentException();if(concurrencyLevel>MAX_SEGMENTS)concurrencyLevel=MAX_SEGMENTS;//Findpower-of-twosizesbestmatchingargumentsintsshift=0;intssize=1;while(ssize<concurrencyLevel){++sshift;ssize?=1;this.segmentShift=32-sshift;this.segmentMask=ssize一1;if(initialcapacity>MAXIMUM__CAPACITY)initialcapacity=MAXIMUM^CAPACITY;intc=initialcapacity/ssize;if(c*ssize<initialcapacity)++c;intcap=MIN_SEGMENT_TABLE__CAPACITY;while(cap<c)cap?=1;//createsegmentsandsegments[0]Segment<K,V>sO=newSegment<KzV>(loadFactor,(int)(cap*loadFactor),<=0)(HashEntry<K,V>[])newHashEntry[cap]);Segment<K,V>[]ss=(Segment<K,V>[])newSegment[ssize];CWSAFE.putOrderedObject(ss,SBASE,sO);//orderedwriteofsegments[0]this.segments=ss;截圖(Alt+A)|Vvalue)Segment<K^V>s;Vvalue)Segment<K^V>s;if(value==null)thrownewNullPointerException();inthash=ha.sh(key);intj=(hash?>segmentShift)&segmentMask;if((□=(Segment<K,V>)tWSAFS.getObject //nonvolatile;recheck(segments,(j?SSHIFT)+SBASE))==null)//inensureSegments=ensureSegment(j);returns.put(key,hash,value,false);ConcurrentHashMap引入了分割(Segment),上面代碼中的最后一行其實就可以理解為把一個大的Map拆分成N個小的HashTable,在put方法中,會根據hash(paramK.hashCode())來決定具體存放進哪個Segment,如果查看Segment的put操作,我們會發(fā)現內部使用的同步機制是基于lock操作的,這樣就可以對Map的一部分(Segment)進行上鎖,這樣影響的只是將要放入同一個Segment的元素的put操作,保證同步的時候,鎖住的不是整個Map(HashTable就是這么做的),相對于HashTable提高了多線程環(huán)境下的性能,因此HashTable已經被淘汰了。1.3線程1.3.1創(chuàng)建線程的方式及實現Java中創(chuàng)建線程主要有三種方式:一、繼承Thread類創(chuàng)建線程類定義Thread類的子類,并重寫該類的run方法,該run方法的方法體就代表了線程要完成的任務。因此把run()方法稱為執(zhí)行體。創(chuàng)建Thread子類的實例,即創(chuàng)建了線程對象。調用線程對象的start()方法來啟動該線程。二、 通過Runnable接口創(chuàng)建線程類定義runnable接口的實現類,并重寫該接口的run()方法,該run()方法的方法體同樣是該線程的線程執(zhí)行體。創(chuàng)建Runnable實現類的實例,并依此實例作為Thread的target來創(chuàng)建Thread對象,該Thread對象才是真正的線程對象。調用線程對象的start()方法來啟動該線程。三、 通過Callable和Future創(chuàng)建線程創(chuàng)建Callable接口的實現類,并實現call()方法,該call()方法將作為線程執(zhí)行體,并且有返回值。創(chuàng)建Callable實現類的實例,使用FutureTask類來包裝Callable對象,該FutureTask對象封裝了該Callable對象的call()方法的返回值。使用FutureTask對象作為Thread對象的target創(chuàng)建并啟動新線程。調用FutureTask對象的get()方法來獲得子線程執(zhí)行結束后的返回值publicclassCalla.bleThreadTestimplementsCa.lla.ble<Integer>{publicstaticvoidma.in(String[]args)throwsInterruptedExceptionfExecutionException{Ca.lla.bleThreadTestctt=newCa.lla.bleThrea.dTest();FutureTa.sk<Integer>ft=newFutureTa.sk<Integer>(ctt);Threadt=newThread(ft,"FutureTask");t.stairt();System,out.printIn("FutureTask.get=,r+ft.get());publicIntegercall()throwsException{inti=0;for(;i<5;i++){System.out.printin(Thread.currentThread().getName()+""+i)returni;創(chuàng)建線程的三種方式的對比采用實現Runnable、Callable接口的方式創(chuàng)見多線程時,優(yōu)勢是:線程類只是實現了Runnable接口或Callable接口,還可以繼承其他類。在這種方式下,多個線程可以共享同一個target對象,所以非常適合多個相同線程來處理同一份資源的情況,從而可以將CPU、代碼和數據分開,形成清晰的模型,較好地體現了面向對象的思想。劣勢是:編程稍微復雜,如果要訪問當前線程,則必須使用Thread.currentThread()方法。使用繼承Thread類的方式創(chuàng)建多線程時優(yōu)勢是:編寫簡單,如果需要訪問當前線程,則無需使用Thread.currentThread()方法,直接使用this即可獲得當前線程。劣勢是:線程類已經繼承了Thread類,所以不能再繼承其他父類。sleep()、join()、Rield()有什么區(qū)別1、sleep()方法在指定的毫秒數內讓當前正在執(zhí)行的線程休眠(暫停執(zhí)行),此操作受到系統(tǒng)計時器和調度程序精度和準確性的影響。讓其他線程有機會繼續(xù)執(zhí)行,但它并不釋放對象鎖。也就是如果有SRnchronized同步塊,其他線程仍然不能訪問共享數據。注意該方法要捕獲異常
比如有兩個線程同時執(zhí)行(沒有SRnchronized),一個線程優(yōu)先級為MAR_PRIORITR,另一個為MIN_PRIORITR,如果沒有Sleep()方法,只有高優(yōu)先級的線程執(zhí)行完成后,低優(yōu)先級的線程才能執(zhí)行;但當高優(yōu)先級的線程sleep(5000)后,低優(yōu)先級就有機會執(zhí)行了??傊?,sleep()可以使低優(yōu)先級的線程得到執(zhí)行的機會,當然也可以讓同優(yōu)先級、高優(yōu)先級的線程有執(zhí)行的機會。2、 Rield()方法Rield()方法和sleep()方法類似,也不會釋放“鎖標志”,區(qū)別在于,它沒有參數,即Rield()方法只是使當前線程重新回到可執(zhí)行狀態(tài),所以執(zhí)行Rield()的線程有可能在進入到可執(zhí)行狀態(tài)后馬上又被執(zhí)行,另外Rield()方法只能使同優(yōu)先級或者高優(yōu)先級的線程得到執(zhí)行機會,這也和sleep()方法不同。3、 join()方法Thread的非靜態(tài)方法join()讓一個線程B“加入”到另外一個線程A的尾部。在A執(zhí)行完畢之前,B不能工作。Threadt=newMRThread();t.start();t.join();保證當前線程停止執(zhí)行,直到該線程所加入的線程完成為止。然而,如果它加入的線程沒有存活,則當前線程不需要停止。說說CountDownLatch原理CountDownLatch是同步工具類之一,可以指定一個計數值,在并發(fā)環(huán)境下由線程進行減1操作,當計數值變?yōu)?之后,被await方法阻塞的線程將會喚醒,實現線程間的同步。1、構造器。CountDownLatch是同步工具類之一,可以指定一個計數值,在并發(fā)環(huán)境下由線程進行減1操作,當計數值變?yōu)?之后,被await方法阻塞的線程將會喚醒,實現線程間的同步。1、構造器。構造函數很簡單地傳遞計數值給SRnc,并且設置了state。y**LConstructsa{@codeCotintDownLa.tc!h}initializedwiththegivencount.@paramcountthenumberoftimes{@link#countDown}mustbeinvokedbeforethreadscanpassthrough{@link#awa.it}@throwsIllegalArgLimentExceptionif{@codecount}isnegativeCountDownLatch(intcount){2、publicvoid2、publicvoidawaitif(count<0)thrownewIllega.lArguin&ntException("count<0rr);this.sync=newSync(count);阻塞線程。await方法,直接調用了AQS(即SRnc)的acquireSharedInterruptiblR()throwsInterruptedException{publicfinalvoidacquireSharedlnterruptibl(intarg)throwsInterruptedException{if(Terrupted())thrownewInterruptedException();if(tryAcquireShared(arg)<0)publicfinalvoidacquireSharedlnterruptibl(intarg)throwsInterruptedException{if(Terrupted())thrownewInterruptedException();if(tryAcquireShared(arg)<0)doAcquireSharedlnterruptibly(a.rg);首先嘗試獲取共享鎖,實現方式和獨占鎖類似,由CountDownLatch實現判斷邏輯。protectedinttryAcquireShare51(intacquires)return(getState()==0)?1:-1;返回1代表獲取成功,返回-1代表獲取失敗。如果獲取失敗,需要調用doAcquireSharedInterruptiblR:**Acquiresinsharedinterruptiblemode.@paramargtheacquireargument/privatevoiddoAcquireSharedlnterruptibly(intprivatevoiddoAcquireSharedlnterruptibly(intarg)throwsInterruptedException{finalNodenode=addWaiter(Node*SHARED);failed.=failed.=true;try{forfinalNodep=node.predecessor();if(p==head){intr=tryAcquireShared(arg);if(r>=0){□etHea.dAndPropaga.te(node,r);p.next=null;//helpGCfailed=false;return;if(shouldParkAfterFailedAcquire(p,node)&&parkAndChecklnterrupt())thrownewInterruptedException();}finally{if(failed)cancelAcquire(node);doAcquireSharedInterruptiblR的邏輯和獨占功能具體如下:創(chuàng)建的Node是定義成共享的(Node.SHARED);被喚醒后重新嘗試獲取鎖,不只設置自己為head,還需要通知其他等待的線程。(重點看后文釋放操作里的setHeadAndPropagate)3、釋放操作。countDown操作實際就是釋放鎖的操作,每調用一次,計數值減少1。Decrementsthecountofthe leleasingallwaitingthreadsif七thecountreacheszero.<p>lfthecurrentcountisgreaterthanzerothenitisdeciemeu*■Ifthenewcountzerothenallwaitingthreadsarereenabledfor'threadschedulingpu‘、p《此;號日,*■<p>Ifthecurrentcountequal□zerothennothinghappens.*/publicvoidcountdown()(aync,releaseShared(1);
/***/Releasesinsharedmode.Implementedbyunblockingoneormorethreadsif{@link#tryRelea.seShared}returnstrue*@paramargthereleaseargument./***/{@link#tryReleaseShared}butisotherwiseuninterpretedandcanrepresentanythingyoulike.?returnthevaluereturnedfrom{@link#tryReleaseShared}publicfinalbooleanrelea.seShared(intarg){if(tryRelea.seShared(arg)){doReleaseShared();returntrue;returnfalse;同樣是首先嘗試釋放鎖,具體實現在CountDownLatch中:同樣是首先嘗試釋放鎖,具體實現在CountDownLatch中:protectedboolean//Decrementcojnt;signaluh&ntransitiontoz^rofor(;;)(intc=geti'tate();if(c—0)returnfalse;intnextc=c-L;if(compareAndS'-.H.^tate(cfnext::))returnnextj一一0;死循環(huán)加上cas的方式保證state的減1操作,當計數值等于0,代表所有子線程都執(zhí)行完畢,被await阻塞的線程可以喚醒了,下一步調用doReleaseShared:doReleaseShare9(){/*1,NodehdoReleaseShare9(){/*1,NodehEnsurethatareleasepropagatesrevenifthereareotherin-progressacquires/releaises.ThisproceedsintheusualwayoftryingtounparkSuccessorofheadifitneedssignal.Butifitdoesnot,statusissettoPROPAGATEtoensurethatuponrelease,propagationcontinues.Additionally,wemustloopincaseanewnodeiswhilewearedoingthis.Also,unlikeotherusesunparkSuccessor,weneedtoknowifCAStoresetfails,ifsorechecking.addedofstatushead;null&&h!=tail){h*wa.itStatus;if(ws==Node.SIGWAZ){(h!=intwsReleaseactionforsharedmode--signalsuccessorandensurepropagation.(Note:Forexclusivemode,releasejustamountstocallingunparkSuccessorofheadifitneedssigna.1.)*/privatevoidtorecheckcasesif(!compa.reAndSetVla.itSta.tus(h,Node.SIGNAL,0))continue; //looptorecheckcasesunparkSuccessor(h);}elseif(ws==0&&0,Node0,Node*PROPAGATE))onfailedCAScontinue; //loop//loopifheadchanged(h—head)//loopifheadchanged標記1里,頭節(jié)點狀態(tài)如果SIGNAL,則狀態(tài)重置為0,并調用unparkSuccessor喚醒下個節(jié)點。標記2里,被喚醒的節(jié)點狀態(tài)會重置成0,在下一次循環(huán)中被設置成PROPAGATE狀態(tài),代表狀態(tài)要向后傳播。參考:分析CountDownLatch的實現原理什么時候使用CountDownLatchJava并發(fā)編程:CountDownLatch、CRclicBarrier和Semaphore1)CountDownLatch和CRclicBarrier都能夠實現線程之間的等待,只不過它們側重點不同:CountDownLatch一般用于某個線程A等待若干個其他線程執(zhí)行完任務之后,它才執(zhí)行;而CRclicBarrier一般用于一組線程互相等待至某個狀態(tài),然后這一組線程再同時執(zhí)行;另外,CountDownLatch是不能夠重用的,而CRclicBarrier是可以重用的。Semaphore其實和鎖有點類似,它一般用于控制對某組資源的訪問權限。說說CRclicBarrier原理參考:JUC回顧之-CRclicBarrier底層實現和原理說說Semaphore原理JAVA多線程-信號量(Semaphore)JUC回顧之-Semaphore底層實現和原理說說ERchanger原理java.util.concurrent.ERchanger應用范例與原理淺析說說CountDownLatch與CRclicBarrier區(qū)別CountDownLatchCRclicBarrier減計數方式加計數方式計算為0時釋放所有等待的線程計數達到指定值時釋放所有等待線程計數為0時,無法重置計數達到指定值時,計數置為0重新開始調用countDown()方法計數減一,調用await()調用await()方法計數加1,若加1后的值方法只進行阻塞,對計數沒任何影響不等于構造方法的值,則線程阻塞不可重復利用可重復利用盡量把CRclicBarrier和CountDownLatch的區(qū)別說通俗點ThreadLocal原理分析ThreadLocal不是用來解決對象共享訪問問題的,而主要是提供了保持對象的方法和避免參數傳遞的方便的對象訪問方式。歸納了兩點:每個線程中都有一個自己的ThreadLocalMap類對象,可以將線程自己的對象保持到其中,各管各的,線程可以正確的訪問到自己的對象。將一個共用的ThreadLocal靜態(tài)實例作為keR,將不同對象的引用保存到不同線程的ThreadLocalMap中,然后在線程執(zhí)行的各處通過這個靜態(tài)ThreadLocal實例的get()方法取得自己線程保存的那個對象,避免了將這個對象作為參數傳遞的麻煩。Java并發(fā)編程:深入剖析ThreadLocal1.3.9講講線程池的實現原理線程池的具體實現原理,將從下面幾個方面講解:線程池狀態(tài)當創(chuàng)建線程池后,初始時,線程池處于RUNNING狀態(tài);如果調用了shutdown()方法,則線程池處于SHUTDOWN狀態(tài),此時線程池不能夠接受新的任務,它會等待所有任務執(zhí)行完畢;如果調用了shutdownNow()方法,則線程池處于STOP狀態(tài),此時線程池不能接受新的任務,并且會去嘗試終止正在執(zhí)行的任務;當線程池處于SHUTDOWN或STOP狀態(tài),并且所有工作線程已經銷毀,任務緩存隊列已經清空或執(zhí)行結束后,線程池被設置為TERMINATED狀態(tài)。任務的執(zhí)行首先,要清楚corePoolSize和maRimumPoolSize的含義;其次,要知道Worker是用來起到什么作用的;要知道任務提交給線程池之后的處理策略,這里總結一下主要有4點:如果當前線程池中的線程數目小于corePoolSize,則每來一個任務,就會創(chuàng)建一個線程去執(zhí)行這個任務;如果當前線程池中的線程數目>=corePoolSize,則每來一個任務,會嘗試將其添加到任務緩存隊列當中,若添加成功,則該任務會等待空閑線程將其取出去執(zhí)行;若添加失敗(一般來說是任務緩存隊列已滿),則會嘗試創(chuàng)建新的線程去執(zhí)行這個任務;如果當前線程池中的線程數目達到maRimumPoolSize,則會采取任務拒絕策略進彳丁處理;如果線程池中的線程數量大于corePoolSize時,如果某線程空閑時間超過keepAliveTime,線程將被終止,直至線程池中的線程數目不大于corePoolSize;如果允許為核心池中的線程設置存活時間,那么核心池中的線程空閑時間超過keepAliveTime,線程也會被終止。線程池中的線程初始化默認情況下,創(chuàng)建線程池之后,線程池中是沒有線程的,需要提交任務之后才會創(chuàng)建線程。在實際中如果需要線程池創(chuàng)建之后立即創(chuàng)建線程,可以通過以下兩個方法辦到:prestartCoreThread():初始化一個核心線程;prestartAllCoreThreads():初始化所有核心線程注意上面?zhèn)鬟M去的參數是null,如果傳進去的參數為null,則最后執(zhí)行線程會阻塞在getTask方法中的workQueue.take();即等待任務隊列中有任務。任務緩存隊列及排隊策略在前面我們多次提到了任務緩存隊列,即workQueue,它用來存放等待執(zhí)行的任務。workQueue的類型為BlockingQueue<Runnable>,通??梢匀∠旅嫒N類型:ArraRBlockingQueue:基于數組的先進先出隊列,此隊列創(chuàng)建時必須指定大小;LinkedBlockingQueue:基于鏈表的先進先出隊列,如果創(chuàng)建時沒有指定此隊列大小,則默認為Integer.MAR_VALUE;sRnchronousQueue:這個隊列比較特殊,它不會保存提交的任務,而是將直接新建一個線程來執(zhí)行新來的任務。任務拒絕策略當線程池的任務緩存隊列已滿并且線程池中的線程數目達到maRimumPoolSize,如果還有任務到來就會采取任務拒絕策略,通常有以下四種策略:ThreadPoolERecutor.AbortPolicR:丟棄任務并拋出RejectedERecutionERception異常。ThreadPoolERecutor.DiscardPolicR:也是丟棄任務,但是不拋出異常。ThreadPoolERecutor.DiscardOldestPolicR:丟棄隊列最前面的任務,然后重新嘗試執(zhí)行任務(重復此過程)ThreadPoolERecutor.CallerRunsPolicR:由調用線程處理該任務線程池的關閉ThreadPoolERecutor提供了兩個方法,用于線程池的關閉,分別是shutdown()和shutdownNow(),其中:shutdown():不會立即終止線程池,而是要等所有任務緩存隊列中的任務都執(zhí)行完后才終止,但再也不會接受新的任務shutdownNow():立即終止線程池,并嘗試打斷正在執(zhí)行的任務,并且清空任務緩存隊列,返回尚未執(zhí)行的任務線程池容量的動態(tài)調整ThreadPoolERecutor提供了動態(tài)調整線程池容量大小的方法:setCorePoolSize()和setMaRimumPoolSize(),setCorePoolSize:設置核心池大小setMaRimumPoolSize:設置線程池最大能創(chuàng)建的線程數目大小當上述參數從小變大時,ThreadPoolERecutor進行線程賦值,還可能立即創(chuàng)建新的線程來執(zhí)行任務。主要是ThreadPoolERecutor的實現原理Java并發(fā)編程:線程池的使用線程池的幾種方式newFiRedThreadPool(intnThreads)創(chuàng)建一個固定長度的線程池,每當提交一個任務就創(chuàng)建一個線程,直到達到線程池的最大數量,這時線程規(guī)模將不再變化,當線程發(fā)生未預期的錯誤而結束時,線程池會補充一個新的線程newCachedThreadPool()創(chuàng)建一個可緩存的線程池,如果線程池的規(guī)模超過了處理需求,將自動回收空閑線程,而當需求增加時,則可以自動添加新線程,線程池的規(guī)模不存在任何限制newSingleThreadERecutor()這是一個單線程的ERecutor,它創(chuàng)建單個工作線程來執(zhí)行任務,如果這個線程異常結束,會創(chuàng)建一個新的來替代它;它的特點是能確保依照任務在隊列中的順序來串行執(zhí)行newScheduledThreadPool(intcorePoolSize)創(chuàng)建了一個固定長度的線程池,而且以延遲或定時的方式來執(zhí)行任務,類似于Timer。參考:創(chuàng)建線程池的幾種方式線程的生命周期新建(New)、就緒(Runnable)、運行(Running)、阻塞(Blocked)和死亡(Dead)5種狀態(tài)(1)生命周期的五種狀態(tài)新建(newThread)當創(chuàng)建Thread類的一個實例(對象)時,此線程進入新建狀態(tài)(未被啟動)。例如:Threadt1=newThread();就緒(runnable)線程已經被啟動,正在等待被分配給CPU時間片,也就是說此時線程正在就緒隊列中排隊等候得到CPU資源。例如:t1.start();運行(running)線程獲得CPU資源正在執(zhí)行任務(run()方法),此時除非此線程自動放棄CPU資源或者有優(yōu)先級更高的線程進入,線程將一直運行到結束。死亡(dead)當線程執(zhí)行完畢或被其它線程殺死,線程就進入死亡狀態(tài),這時線程不可能再進入就緒狀態(tài)等待執(zhí)行。自然終止:正常運行run()方法后終止異常終止:調用stop()方法讓一個線程終止運行堵塞(blocked)由于某種原因導致正在運行的線程讓出CPU并暫停自己的執(zhí)行,即進入堵塞狀態(tài)。正在睡眠:用sleep(longt)方法可使線程進入睡眠方式。一個睡眠著的線程在指定的時間過去可進入就緒狀態(tài)。正在等待:調用wait()方法。(調用motifR()方法回到就緒狀態(tài))被另一個線程所阻塞:調用suspend()方法。(調用resume()方法恢復)參考:線程的生命周期1.4鎖機制1.4.1說說線程安全問題線程安全是指要控制多個線程對某個資源的有序訪問或修改,而在這些線程之間沒有產生沖突。在Java里,線程安全一般體現在兩個方面:多個thread對同一個java實例的訪問(read和modifR)不會相互干擾,它主要體現在關鍵字sRnchronized。如ArraRList和Vector,HashMap和Hashtable(后者每個方法前都有sRnchronized關鍵字)。如果你在interator一個List對象時,其它線程remove一個element,問題就出現了。每個線程都有自己的字段,而不會在多個線程之間共享。它主要體現在java.lang.ThreadLocal類,而沒有Java關鍵字支持,如像static、transient那樣。volatile實現原理Volatile是輕量級的sRnchronized,它在多處理器開發(fā)中保證了共享變量的“可見性”??梢娦缘囊馑际钱斠粋€線程修改一個共享變量時,另外一個線程能讀到這個修改的值。它在某些情況下比sRnchronized的開銷更小,本文將深入分析在硬件層面上Inter處理器是如何實現Volatile的,通過深入分析能幫助我們正確的使用Volatile變量。聊聊并發(fā)(一)一一深入分析Volatile的實現原理1.4.3悲觀鎖樂觀鎖樂觀鎖悲觀鎖是一種思想??梢杂迷诤芏喾矫妗1热鐢祿旆矫?。悲觀鎖就是forupdate(鎖定查詢的行)樂觀鎖就是version字段(比較跟上一次的版本號,如果一樣則更新,如果失敗則要重復讀-比較-寫的操作。)JDK方面:悲觀鎖就是sRnc樂觀鎖就是原子類(內部使用CAS實現)本質來說,就是悲觀鎖認為總會有人搶我的。樂觀鎖就認為,基本沒人搶。CAS樂觀鎖樂觀鎖是一種思想,即認為讀多寫少,遇到并發(fā)寫的可能性比較低,所以采取在寫時先讀出當前版本號,然后加鎖操作(比較跟上一次的版本號,如果一樣則更新),如果失敗則要重復讀-比較-寫的操作。CAS是一種更新的原子操作,比較當前值跟傳入值是否一樣,一樣則更新,否則失敗。CAS頂多算是樂觀鎖寫那一步操作的一種實現方式罷了,不用CAS自己加鎖也是可以的。ABA問題ABA:如果另一個線程修改V值假設原來是A,先修改成B,再修改回成A,當前線程的CAS操作無法分辨當前V值是否發(fā)生過變化。參考:JavaCAS和ABA問題1.4.5樂觀鎖的業(yè)務場景及實現方式樂觀鎖(OptimisticLock):每次獲取數據的時候,都不會擔心數據被修改,所以每次獲取數據的時候都不會進行加鎖,但是在更新數據的時候需要判斷該數據是否被別人修改過。如果數據被其他線程修改,則不進行數據更新,如果數據沒有被其他線程修改,則進行數據更新。由于數據沒有進行加鎖,期間該數據可以被其他線程進行讀寫操作。樂觀鎖:比較適合讀取操作比較頻繁的場景,如果出現大量的寫入操作,數據發(fā)生沖突的可能性就會增大,為了保證數據的一致性,應用層需要不斷的重新獲取數據,這樣會增加大量的查詢操作,降低了系統(tǒng)的吞吐量。2.1數據存儲MRSQL索引使用的注意事項參考:mRsql索引使用技巧及注意事項2.1.2說說反模式設計參考:每個程序員要注意的9種反模式2.1.3說說分庫與分表設計分表與分庫使用場景以及設計方式2.1.4分庫與分表帶來的分布式困境與應對之策服務端指南數據存儲篇|MRSQL(09)分庫與分表帶來的分布式困境與應對之策2.1.5說說SQL優(yōu)化之道sql優(yōu)化的幾種方法2.1.6MRSQL遇到的死鎖問題參考:MRsql并發(fā)時經典常見的死鎖原因及解決方法2.1.7存儲引擎的InnoDB與MRISAMInnoDB支持事務,MRISAM不支持,這一點是非常之重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪個出錯還可以回滾還原,而MRISAM就不可以了。MRISAM適合查詢以及插入為主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用InnoDB支持外鍵,MRISAM不支持從MRSQL5.5.5以后,InnoDB是默認引擎InnoDB不支持FULLTERT類型的索引InnoDB中不保存表的行數,如selectcount()fromtable時,InnoDB需要掃描一遍整個表來計算有多少行,但是MRISAM只要簡單的讀出保存好的行數即可。注意的是,當count()語句包含where條件時MRISAM也需要掃描整個表對于自增長的字段,InnoDB中必須包含只有該字段的索引,但是在MRISAM表中可以和其他字段一起建立聯(lián)合索引清空整個表時,InnoDB是一行一行的刪除,效率非常慢。MRISAM則會重建表9)InnoDB支持行鎖(某些情況下還是鎖整表,如updatetableseta=1whereuserlike‘%lee%’參考:MRSQL存儲引擎之MRIsam和Innodb總結性梳理2.1.8數據庫索引的原理參考:/suifeng3051/article/details/526696442.1.9為什么要用B-tree鑒于B-tree具有良好的定位特性,其常被用于對檢索時間要求苛刻的場合,例如:1、 B-tree索引是數據庫中存取和查找文件(稱為記錄或鍵值)的一種方法。2、 硬盤中的結點也是B-tree結構的。與內存相比,硬盤必須花成倍的時間來存取一個數據元素,這是因為硬盤的機械部件讀寫數據的速度遠遠趕不上純電子媒體的內存。與一個結點兩個分支的二元樹相比,B-tree利用多個分支(稱為子樹)的結點,減少獲取記錄時所經歷的結點數,從而達到節(jié)省存取時間的目的。聚集索引與非聚集索引的區(qū)別參考:快速理解聚集索引和非聚集索引limit20RR0加載很慢怎么解決LIMITn等價于LIMIT0,n此題總結一下就是讓limit走索引去查詢,例如:orderbR索引字段,或者limit前面根where條件走索引字段等等。參考:MRSQL分頁limit速度太慢優(yōu)化方法選擇合適的分布式主鍵方案參考:分布式系統(tǒng)唯一ID生成方案匯總選擇合適的數據存儲方案關系型數據庫MRSQLMRSQL是一個最流行的關系型數據庫,在互聯(lián)網產品中應用比較廣泛。一般情況下,MRSQL數據庫是選擇的第一方案,基本上有80%~90%的場景都是基于MRSQL數據庫的。因為,需要關系型數據庫進行管理,此外,業(yè)務存在許多事務性的操作,需要保證事務的強一致性。同時,可能還存在一些復雜的SQL的查詢。值得注意的是,前期盡量減少表的聯(lián)合查詢,便于后期數據量增大的情況下,做數據庫的分庫分表。內存數據庫Redis隨著數據量的增長,MRSQL已經滿足不了大型互聯(lián)網類應用的需求。因此,Redis基于內存存儲數據,可以極大的提高查詢性能,對產品在架構上很好的補充。例如,為了提高服務端接口的訪問速度,盡可能將讀頻率高的熱點數據存放在Redis中。這個是非常典型的以空間換時間的策略,使用更多的內存換取CPU資源,通過增加系統(tǒng)的內存消耗,來加快程序的運行速度。在某些場景下,可以充分的利用Redis的特性,大大提高效率。這些場景包括緩存,會話緩存,時效性,訪問頻率,計數器,社交列表,記錄用戶判定信息,交集、并集和差集,熱門列表與排行榜,最新動態(tài)等。使用Redis做緩存的時候,需要考慮數據不一致與臟讀、緩存更新機制、緩存可用性、緩存服務降級、緩存穿透、緩存預熱等緩存使用問題。文檔數據庫MongoDBMongoDB是對傳統(tǒng)關系型數據庫的補充,它非常適合高伸縮性的場景,它是可擴展性的表結構。基于這點,可以將預期范圍內,表結構可能會不斷擴展的MRSQL表結構,通過MongoDB來存儲,這就可以保證表結構的擴展性。此外,日志系統(tǒng)數據量特別大,如果用MongoDB數據庫存儲這些數據,利用分片集群支持海量數據,同時使用聚集分析和MapReduce的能力,是個很好的選擇。MongoDB還適合存儲大尺寸的數據,GridFS存儲方案就是基于MongoDB的分布式文件存儲系統(tǒng)。列族數據庫HBaseHBase適合海量數據的存儲與高性能實時查詢,它是運行于HDFS文件系統(tǒng)之上,并且作為MapReduce分布式處理的目標數據庫,以支撐離線分析型應用。在數據倉庫、數據集市、商業(yè)智能等領域發(fā)揮了越來越多的作用,在數以千計的企業(yè)中支撐著大量的大數據分析場景的應用。全文搜索引擎ElasticSearch在一般情況下,關系型數據庫的模糊查詢,都是通過 like的方式進行查詢。其中,like“value%”可以使用索引,但是對于like“%value%”這樣的方式,執(zhí)行全表查詢,這在數據量小的表,不存在性能問題,但是對于海量數據,全表掃描是非??膳碌氖虑椤lasticSearch作為一個建立在全文搜索引擎ApacheLucene基礎上的實時的分布式搜索和分析引擎,適用于處理實時搜索應用場景。此外,使用ElasticSearch全文搜索引擎,還可以支持多詞條查詢、匹配度與權重、自動聯(lián)想、拼寫糾錯等高級功能。因此,可以使用ElasticSearch作為關系型數據庫全文搜索的功能補充,將要進行全文搜索的數據緩存一份到ElasticSearch上,達到處理復雜的業(yè)務與提高查詢速度的目的。ElasticSearch不僅僅適用于搜索場景,還非常適合日志處理與分析的場景。著名的ELK日志處理方案,由ElasticSearch、Logstash和Kibana三個組件組成,包括了日志收集、聚合、多維度查詢、可視化顯示等。ObjectId規(guī)則參考:MongoDB學習筆記~ObjectId主鍵的設計mongodb中的_id的ObjectId的生成規(guī)則聊聊MongoDB使用場景參考:什么場景應該用MongoDB?倒排索引參考:什么是倒排索引?聊聊ElasticSearch使用場景在一般情況下,關系型數據庫的模糊查詢,都是通過 like的方式進行查詢。其中,like“value%”可以使用索引,但是對于like“%value%”這樣的方式,執(zhí)行全表查詢,這在數據量小的表,不存在性能問題,但是對于海量數據,全表掃描是非??膳碌氖虑?。ElasticSearch作為一個建立在全文搜索引擎ApacheLucene基礎上的實時的分布式搜索和分析引擎,適用于處理實時搜索應用場景。此外,使用ElasticSearch全文搜索引擎,還可以支持多詞條查詢、匹配度與權重、自動聯(lián)想、拼寫糾錯等高級功能。因此,可以使用ElasticSearch作為關系型數據庫全文搜索的功能補充,將要進行全文搜索的數據緩存一份到ElasticSearch上,達到處理復雜的業(yè)務與提高查詢速度的目的。2.2緩存使用Redis有哪些類型Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sortedset:有序集合)。參考:Redis數據類型Redis內部結構參考:redis內部數據結構深入淺出2.2.3聊聊Redis使用場景隨著數據量的增長,MRSQL已經滿足不了大型互聯(lián)網類應用的需求。因此,Redis基于內存存儲數據,可以極大的提高查詢性能,對產品在架構上很好的補充。例如,為了提高服務端接口的訪問速度,盡可能將讀頻率高的熱點數據存放在Redis中。這個是非常典型的以空間換時間的策略,使用更多的內存換取CPU資源,通過增加系統(tǒng)的內存消耗,來加快程序的運行速度。在某些場景下,可以充分的利用Redis的特性,大大提高效率。這些場景包括緩存,會話緩存,時效性,訪問頻率,計數器,社交列表,記錄用戶判定信息,交集、并集和差集,熱門列表與排行榜,最新動態(tài)等。使用Redis做緩存的時候,需要考慮數據不一致與臟讀、緩存更新機制、緩存可用性、緩存服務降級、緩存穿透、緩存預熱等緩存使用問題。Redis持久化機制參考:redis的持久化和緩存機制Redis如何實現持久化參考:Redis如何實現持久化Redis集群方案與實現參考:redis集群主流架構方案分析Redis為什么是單線程的單純的網絡io來說,量大到一定程度之后,多線程的確有優(yōu)勢一一但并不是單純的多線程,而是每個線程自己有自己的epoll這樣的模型,也就是多線程和multipleRing混合。一般這個開頭我們都會跟一個“但是”。但是。還要考慮Redis操作的對象。它操作的對象是內存中的數據結構。如果在多線程中操作,那就需要為這些對象加鎖。最終來說,多線程性能有提高,但是每個線程的效率嚴重下降了。而且程序的邏輯嚴重復雜化。要知道Redis的數據結構并不全是簡單的KeR-Value,還有列表,hash,map等等復雜的結構,這些結構有可能會進行很細粒度的操作,比如在很長的列表后面添加一個元素,在hash當中添加或者刪除一個對象,等等。這些操作還可以合成MULTI/EREC的組。這樣一個操作中可能就需要加非常多的鎖,導致的結果是同步開銷大大增加。這還帶來一個惡果就是吞吐量雖然增大,但是響應延遲可能會增加。Redis在權衡之后的選擇是用單線程,突出自己功能的靈活性。在單線程基礎上任何原子操作都可以幾乎無代價地實現,多么復雜的數據結構都可以輕松運用,甚至可以使用Lua腳本這樣的功能。對于多線程來說這需要高得多的代價。并不是所有的KV數據庫或者內存數據庫都應該用單線程,比如ZooKeeper就是多線程的,最終還是看作者自己的意愿和取舍。單線程的威力實際上非常強大,每核心效率也非常高,在今天的虛擬化環(huán)境當中可以充分利用云化環(huán)境來提高資源利用率。多線程自然是可以比單線程有更高的性能上限,但是在今天的計算環(huán)境中,即使是單機多線程的上限也往往不能滿足需要了,需要進一步摸索的是多服務器集群化的方案,這些方案中多線程的技術照樣是用不上的,所以單線程、多進程的集群不失為一個時髦的解決方案。作者:靈劍鏈接:/question/23162208/answer/142424042來源:知乎著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。2.2.8緩存奔潰參考:Redis持久化2.2.9緩存降級服務降級的目的,是為了防止Redis服務故障,導致數據庫跟著一起發(fā)生雪崩問題。因此,對于不重要的緩存數據,可以采取服務降級策略,例如一個比較常見的做法就是,Redis出現問題,不去數據庫查詢,而是直接返回默認值給用戶。使用緩存的合理性問題參考:Redis實戰(zhàn)(一)使用緩存合理性2.3消息隊列2.3.1消息隊列的使用場景主要解決應用耦合,異步消息,流量削鋒等問題消息
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年全球及中國瓦楞紙板輸送帶行業(yè)頭部企業(yè)市場占有率及排名調研報告
- 2025-2030全球RF IC 設計服務行業(yè)調研及趨勢分析報告
- 2025年全球及中國拖拽式滴鹽撒播機行業(yè)頭部企業(yè)市場占有率及排名調研報告
- 2025年全球及中國運水式模溫機行業(yè)頭部企業(yè)市場占有率及排名調研報告
- 中國居民膳食指南準則一食物多樣合理搭配講解
- 作用于中樞神經系統(tǒng)的藥物講解
- 2025軟件產品代理版合同書
- 安防設備采購政府采購合同
- 2025房屋抵押貸款的合同范本
- 2025承運合同書范本范文
- 民辦幼兒園務工作計劃
- 2025年華僑港澳臺生聯(lián)招考試高考地理試卷試題(含答案詳解)
- 中國革命戰(zhàn)爭的戰(zhàn)略問題(全文)
- 《數學歸納法在中學解題中的應用研究》9000字(論文)
- 《大學英語四級詞匯大全》
- 第六章-1八綱辨證
- 《工業(yè)機器人系統(tǒng)維護(ABB模塊)》試卷10套
- 危險性化合物的微生物降解-中國石油大學環(huán)境生物工程
- 浙江省名校新2025屆高一數學第一學期期末達標檢測試題含解析
- 學習2024《關于加強社會組織規(guī)范化建設推動社會組織高質量發(fā)展的意見》解讀課件
- 2024年縣全民健身活動狀況調查活動方案
評論
0/150
提交評論