一绑警、String,StringBuffer, StringBuilder 的區(qū)別是什么?String為什么是不可變的央渣?
String是字符串常量计盒,所指向的內(nèi)容是不可變的,因?yàn)镾tring 在JDK中聲明為final類芽丹。StringBuffer和StringBuilder是變量北启。
StringBuffer是線程安全的,StringBuilder是線程不安全的,如果只用在單線程中咕村,StringBuilder的效率高于StringBuffer场钉。
二、Vector,ArrayList, LinkedList的區(qū)別是什么懈涛?
Vector和ArrayList的底層是基于數(shù)組形式的逛万,而LinkedList底層是基于鏈表的,前兩者適合查找肩钠,不適合特定位置的插入和刪除泣港,LinkedList適合插入,不適合查找价匠。Vector是線程安全同步的当纱,而ArrayList、LinkedList是線程不安全不同步的踩窖。
三坡氯、HashTable, HashMap,TreeMap區(qū)別洋腮?
HashTable是線程安全同步的箫柳,不允許有鍵值有null的出現(xiàn)。HashMap是線程不安全不同步的啥供,允許有null的出現(xiàn)悯恍,注意會(huì)問到hashcode的作用(兩個(gè)不同對象的hashcode可能是一樣的,而兩個(gè) 對象hashcode不同伙狐,則兩個(gè)對象肯定不同涮毫,所以插入hashmap先用hashcode進(jìn)行對比,如果相同再用equal進(jìn)行判斷)贷屎。TreeMap是默認(rèn)按照鍵的升序進(jìn)行排列的罢防。
四、Tomcat唉侄,Apache咒吐,JBoss的區(qū)別?
Tomcat是Web服務(wù)器属划,Apache是Http服務(wù)器恬叹,JBoss是應(yīng)用服務(wù)器。Tomcat可以解析動(dòng)態(tài)的jsp頁面榴嗅,還可以充當(dāng)servlet容器妄呕。Apache可以解析靜態(tài)的html頁面。
五嗽测、Session, Cookie區(qū)別
Session保存的是服務(wù)器端信息绪励,Cookie保存的是瀏覽器端信息肿孵。用戶可以通過瀏覽器設(shè)置是否保存Cookie,但不能設(shè)置Session疏魏,Cookie和Session都是用來跟蹤用戶信息的停做,Cookie保存的是字符串,Session保存的是對象大莫。
六蛉腌、Servlet的生命周期
init()
service()負(fù)責(zé)處理來自客戶端的請求
destroy()銷毀servlet對象,并釋放其占用資源
七只厘、Statement與PreparedStatement的區(qū)別,什么是SQL注入烙丛,如何防止SQL注入
PreparedStatement支持動(dòng)態(tài)參數(shù)的綁定,而Statement不支持
PreparedStatemen支持預(yù)編譯羔味,而Statement不支持
PreparedStatement可以防止惡意的SQL注入
所謂的SQL注入是指通過sql語句的拼接達(dá)到無參數(shù)查詢數(shù)據(jù)庫的目的河咽,PreparedStatement支持在服務(wù)器端接收參數(shù)后,自動(dòng)驗(yàn)證赋元,而Statement需要手工驗(yàn)證忘蟹。
SQL注入原理是把SQL命令插入到WEB表單提交或輸入域名或頁面請求的查詢字符串,最終欺騙服務(wù)器達(dá)到惡意SQL命令搁凸。
預(yù)防措施:
1)不要相信用戶的輸入媚值,需要對其進(jìn)行驗(yàn)證
2)不要?jiǎng)討B(tài)拼接SQL語句,可以使用參數(shù)化的sql
3)不要把機(jī)密信息直接存放护糖,加密或者h(yuǎn)ash掉密碼和敏感的信息
八褥芒、sendRedirect, foward區(qū)別
forward是服務(wù)器端控制頁面轉(zhuǎn)向,在瀏覽器端并不會(huì)轉(zhuǎn)向的地址嫡良。而sendRedirect是完全的跳轉(zhuǎn)喂很,瀏覽器中顯示轉(zhuǎn)向的地址
九、談?wù)刪ibernate的理解皆刺,一級和二級緩存的作用,在項(xiàng)目中Hibernate都是怎么使用緩存的凌摄。
臨時(shí)狀態(tài):不在session緩存中羡蛾,數(shù)據(jù)庫中沒有對象記錄
持久化對象:在session緩存中,數(shù)據(jù)庫中沒有對象記錄锨亏,session在特定時(shí)候保持兩者同步痴怨,具有唯一OID
游離對象:由持久化對象轉(zhuǎn)換而來,數(shù)據(jù)庫中沒有對象記錄器予,不再處于session緩存中浪藻,調(diào)用session的evict(),close()方法可以刪除session中的對象
一級緩存就是session,是hibernate自帶的,二級緩存是sessionFactory乾翔。
Hibernate二級緩存的策略一般是:
1)條件查詢的時(shí)候爱葵,SQL語句SELECT * FROM table_name WHERE查詢出所有的數(shù)據(jù)對象
2)把獲取的所有對象根據(jù)ID放入到二級緩存中
3)當(dāng)Hibernate通過ID訪問對象時(shí)施戴,先從一級緩存中找,再從二級緩存中找萌丈,如果都不存在赞哗,則去數(shù)據(jù)庫中找
4)刪除、更新辆雾、添加數(shù)據(jù)同步更新緩存
十肪笋、反射講一講,主要是概念,都在哪需要反射機(jī)制度迂,反射的性能藤乙,如何優(yōu)化
反射機(jī)制是指在運(yùn)行過程中,對于任意一個(gè)類惭墓,能獲取這個(gè)類的所有屬性和方法坛梁。對于任意一個(gè)對象,能夠調(diào)用它的任意一個(gè)方法诅妹。這種動(dòng)態(tài)獲取信息及動(dòng)態(tài)調(diào)用對象的方法稱為反射罚勾。
反射提供的功能:
1.在運(yùn)行過程中判斷一個(gè)對象所屬的類
2.構(gòu)造任意一個(gè)類的對象
3.判斷一個(gè)類所具有的屬性和方法
4.調(diào)用任意對象的方法
5.動(dòng)態(tài)代理
十一、對Spring的理解吭狡,項(xiàng)目中都用什么尖殃?怎么用的?對IOC划煮、和AOP的理解及實(shí)現(xiàn)原理
IOC:是指組件之間的依賴關(guān)系是由容器在運(yùn)行過程中決定的送丰,依賴注入的方式有兩種,通過構(gòu)造函數(shù)和set方法
AOP:面向切面編程弛秋,例如把核心業(yè)務(wù)模塊中重復(fù)的代碼重構(gòu)封裝起來器躏,比如配置日置。在Spring Aop中蟹略,存在下面幾種通知
1)前置通知
2)后置通知
3)異常通知
4)環(huán)繞通知:攔截對目標(biāo)方法對象調(diào)用
切面:一個(gè)關(guān)注點(diǎn)的模塊化
連接點(diǎn):程序執(zhí)行過程中明確的點(diǎn)登失,如方法的調(diào)用和特定異常的拋出
通知:在特定的連接點(diǎn),AOP框架執(zhí)行的動(dòng)作。例如前置通知挖炬、后置通知等
切入點(diǎn):指定一個(gè)通知將被引發(fā)的一系列的連接點(diǎn)的集合揽浙。
十二、描述struts的工作流程
- 在web應(yīng)用啟動(dòng)時(shí)意敛,會(huì)初始化并加載ActionServlet對象馅巷,ActionServlet會(huì)讀取struts-config.xml配置文件。
- ActionServlet會(huì)根據(jù)客戶端發(fā)出的請求草姻,檢索與用戶請求相匹配的ActionMapping對象钓猬,如果不存在,則返回一個(gè)無效路徑信息撩独。
3)如果不存在ActionForm實(shí)例敞曹,則會(huì)創(chuàng)建一個(gè)該對象账月,并把表單信息保存到其中
4)如果配置了驗(yàn)證表單信息,則會(huì)調(diào)用ActionForm的validate 方法异雁,如果返回null或者沒有錯(cuò)誤信息的ActionErrors,則表單驗(yàn)證成功
5.)ActionServlet會(huì)根據(jù)ActionMapping中包含的映射信息決定請求轉(zhuǎn)發(fā)給哪個(gè)Action捶障,然后調(diào)用該Action的execute()方法。
6)Action的execute()方法會(huì)返回一個(gè)ActionForward對象纲刀,ActionServlet再把請求轉(zhuǎn)發(fā)給ActionForward對象指向的JSP頁面项炼。
7)ActionForward對象指向的JSP頁面生成動(dòng)態(tài)網(wǎng)頁,返回給客戶示绊。
十三锭部、JVM垃圾回收實(shí)現(xiàn)原理。垃圾回收的線程優(yōu)先級面褐。
垃圾回收器主要有三種:串行收集器拌禾、并行收集器、并發(fā)收集器
1)串行收集器展哭,使用單線程處理所有垃圾回收湃窍,效率比較高,但無法發(fā)揮多核處理器的優(yōu)勢匪傍,適合小數(shù)據(jù)量您市,比如100M大小
2)并行收集器,對年輕代進(jìn)行并行回收役衡,減少垃圾回收的時(shí)間茵休,一般在多線程多核處理器上使用。
3)并發(fā)收集器手蝎,大部分時(shí)間都能保證程序是并發(fā)進(jìn)行的榕莺,垃圾回收只占用很少時(shí)間,適合對響應(yīng)要求比較高的中棵介、大規(guī)模應(yīng)用钉鸯。
年輕代:分三個(gè)區(qū),一個(gè)Eden區(qū)邮辽,兩個(gè)Survivor區(qū)亏拉。當(dāng)Eden區(qū)滿的時(shí)候,會(huì)存放到一個(gè)Survivor區(qū)逆巍,當(dāng)這個(gè)Survivor區(qū)也滿了,會(huì)存放到第二個(gè)Survivor區(qū)莽使,如果這個(gè)區(qū)也滿了锐极,會(huì)將從第一個(gè)Survivor區(qū)復(fù)制過來且存活的對象放到年老代中。
年老代:主要存放著從年輕代轉(zhuǎn)化過來的對象芳肌,一般來說是生命周期比較長的對象
持久代:一般是靜態(tài)資源灵再,比如java類和方法等肋层,一般不會(huì)影響垃圾回收。但是一些應(yīng)用可能會(huì)動(dòng)態(tài)生成或者調(diào)用一些class,比如Hibernate,因此需要設(shè)置比較大的持久代空間來存放這些運(yùn)行過程中增加的類翎迁。
十四栋猖、TCP/IP(三次握手,四次揮手)
有6種標(biāo)示:
SYN(synchronous建立聯(lián)機(jī))
ACK(acknowledgement 確認(rèn))
PSH(push傳送)
FIN(finish結(jié)束)
RST(reset重置)
URG(urgent緊急)
Sequence number(順序號(hào)碼) Acknowledge number(確認(rèn)號(hào)碼)
三次握手
1)第一次握手:主機(jī)A發(fā)送位碼為syn=1,隨機(jī)產(chǎn)生seq number=1234567的數(shù)據(jù)包到服務(wù)器,主機(jī)B由SYN=1知道汪榔,A要求建立聯(lián)機(jī)蒲拉;
2)第二次握手:主機(jī)B收到請求后要確認(rèn)聯(lián)機(jī)信息,向A發(fā)送ack number=(主機(jī)A的seq+1),syn=1,ack=1,隨機(jī)產(chǎn)生seq=7654321的包
3)主機(jī)A收到后檢查ack number是否正確痴腌,即第一次發(fā)送的seq number+1,以及位碼ack是否為1雌团,若正確,主機(jī)A會(huì)再發(fā)送ack number=(主機(jī)B的seq+1),ack=1士聪,主機(jī)B收到后確認(rèn)seq值與ack=1則連接建立成功锦援。
四次揮手
1) 客戶端A發(fā)送一個(gè)FIN,用來關(guān)閉客戶A到服務(wù)器B的數(shù)據(jù)傳送
2)服務(wù)器B收到這個(gè)FIN剥悟,它發(fā)回一個(gè)ACK灵寺,確認(rèn)序號(hào)為收到的序號(hào)加1。和SYN一樣区岗,一個(gè)FIN將占用一個(gè)序號(hào)略板。
3)服務(wù)器B關(guān)閉與客戶端A的連接,發(fā)送一個(gè)FIN給客戶端A
4)客戶端A發(fā)回ACK報(bào)文確認(rèn)躏尉,并將確認(rèn)序號(hào)設(shè)置為收到序號(hào)加1蚯根。
客戶端:CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服務(wù)器:CLOSED->LISTEN->SYN收到 ->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
-1. CLOSED: 表示初始狀態(tài)。
-2. LISTEN: 表示服務(wù)器端的某個(gè)SOCKET處于監(jiān)聽狀態(tài)胀糜,可以接受連接了颅拦。
-3. SYN_RCVD: 這個(gè)狀態(tài)表示接受到了SYN報(bào)文
SYN_SENT狀態(tài)表示客戶端已發(fā)送SYN報(bào)文。
-4. ESTABLISHED:表示連接已經(jīng)建立了教藻。
-5. FIN_WAIT_1狀態(tài)實(shí)際上是當(dāng)SOCKET在ESTABLISHED狀態(tài)時(shí)距帅,它想主動(dòng)關(guān)閉連接,向?qū)Ψ桨l(fā)送了FIN報(bào)文括堤,此時(shí)該SOCKET即進(jìn)入到FIN_WAIT_1狀態(tài)碌秸。而當(dāng)對方回應(yīng)ACK報(bào)文后,則進(jìn)入到FIN_WAIT_2狀態(tài)
-6. FIN_WAIT_2:上面已經(jīng)詳細(xì)解釋了這種狀態(tài)悄窃,實(shí)際上FIN_WAIT_2狀態(tài)下的SOCKET讥电,表示半連接,也即有一方要求close連接轧抗,但另外還告訴對方恩敌,我暫時(shí)還有點(diǎn)數(shù)據(jù)需要傳送給你,稍后再關(guān)閉連接横媚。
-7. TIME_WAIT: 表示收到了對方的FIN報(bào)文纠炮,并發(fā)送出了ACK報(bào)文月趟,就等2MSL后即可回到CLOSED可用狀態(tài)了。
-8. CLOSING: 那就是如果雙方幾乎在同時(shí)close一個(gè)SOCKET的話恢口,那么就出現(xiàn)了雙方同時(shí)發(fā)送FIN報(bào)文的情況馒闷,也即會(huì)出現(xiàn)CLOSING狀態(tài)腰埂,表示雙方都正在關(guān)閉SOCKET連接捶索。
-9. CLOSE_WAIT:當(dāng)對方close一個(gè)SOCKET后發(fā)送FIN報(bào)文給自己欲逃,你系統(tǒng)毫無疑問地會(huì)回應(yīng)一個(gè)ACK報(bào)文給對方,此時(shí)則進(jìn)入到CLOSE_WAIT狀態(tài)看疗。接下來呢沙峻,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有的話两芳,那么你也就可以close這個(gè)SOCKET摔寨,發(fā)送FIN報(bào)文給對方,也即關(guān)閉連接怖辆。所以你在CLOSE_WAIT狀態(tài)下是复,需要完成的事情是等待你去關(guān)閉連接。
-10. LAST_ACK: 這個(gè)狀態(tài)還是比較容易好理解的竖螃,它是被動(dòng)關(guān)閉一方在發(fā)送FIN報(bào)文后淑廊,最后等待對方的ACK報(bào)文。當(dāng)收到ACK報(bào)文后特咆,也即可以進(jìn)入到CLOSED可用狀態(tài)了季惩。
為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)?
但是因?yàn)槲覀儽仨氁傧刖W(wǎng)絡(luò)是不可靠的腻格,你無法保證你最后發(fā)送的ACK報(bào)文會(huì)一定被對方收到画拾,因此對方處于LAST_ACK狀態(tài)下的SOCKET可能會(huì)因?yàn)槌瑫r(shí)未收到ACK報(bào)文,而重發(fā)FIN報(bào)文菜职,所以這個(gè)TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報(bào)文
十五青抛、數(shù)據(jù)庫(事務(wù)隔離級別,臟讀,不可重復(fù)讀酬核,幻讀)
臟讀:一個(gè)事務(wù)讀取了另一個(gè)事務(wù)未提交的數(shù)據(jù)
不可重復(fù)讀:比如事務(wù)A 讀取了數(shù)據(jù)蜜另,但是事務(wù)B馬上提交了數(shù)據(jù),此時(shí)A再讀數(shù)據(jù)的話嫡意,就出現(xiàn)了不可重復(fù)數(shù)據(jù)
幻讀:幻讀和不可重復(fù)讀類似举瑰,不可重復(fù)是數(shù)據(jù)發(fā)生了改變,而幻讀是數(shù)據(jù)的記錄數(shù)量發(fā)生了改變
未提交讀:允許其他事務(wù)看到未提交的數(shù)據(jù)蔬螟,會(huì)出現(xiàn)臟讀嘶居,最低級別
已提交讀:被讀取的數(shù)據(jù)可以被其他事務(wù)修改,就是說事務(wù)在讀取數(shù)據(jù)的時(shí)候獲取讀鎖,但是讀完之后立即釋放(不需要等到事務(wù)提交之后)邮屁,而寫鎖是在事務(wù)提交之后釋放。釋放完讀鎖后菠齿,數(shù)據(jù)就可能被其他事務(wù)修改佑吝,產(chǎn)生不可重復(fù)讀
可重復(fù)讀:可以避免臟讀、不可重復(fù)讀绳匀,但不能避免幻讀
串行化:都可以避免
十六芋忿、Linux操作系統(tǒng)
ls mkdir/rmdir cd pwd cp mv ps(查看系統(tǒng)目前進(jìn)程) kill man(在線幫助命令) vi(vi編輯器命令) gedit gcc(編譯器命令) tar chmod(修改權(quán)限) [u所屬用戶 g所屬組 o其他用戶 a所有用戶]
十七、HashMap
HashMap底層就是個(gè)數(shù)組結(jié)構(gòu)疾棵,數(shù)組中的每一項(xiàng)又是一個(gè)鏈表戈钢,Entry<K,V>就是數(shù)組中的元素,他持有指向下一個(gè)元素的引用是尔,就構(gòu)成了鏈表殉了。
HashMap底層把key-value當(dāng)成一個(gè)整體對象來看,即為Entry對象拟枚。HashMap底層用一個(gè)Entry[]保存所有key-value薪铜。當(dāng)需要存儲(chǔ)一個(gè)元素時(shí),先根據(jù)hash算法(一般的hash算法就是hashcode對數(shù)組的長度取模,hashmap這里使用一個(gè)高效的方法,h&(table.length-1,length總為2的n次方恩溅,因此該運(yùn)算等價(jià)于對length取模))確定其在數(shù)組中的存儲(chǔ)位置隔箍,然后通過equals方法確定其在數(shù)組位置上的鏈表中的存儲(chǔ)位置(如果數(shù)組該位置已經(jīng)存放了元素,那么這個(gè)位置上的元素將以鏈表的形式存放脚乡,新加入的在鏈表頭蜒滩,后加入的在鏈表尾,如果數(shù)組該位置上沒有元素奶稠,則直接放在數(shù)組該位置)俯艰。當(dāng)需要從map中獲取一個(gè)元素時(shí),先通過hash算法確定其在數(shù)組中的存儲(chǔ)位置窒典,再通過equals方法從該位置的鏈表中取出該Entry蟆炊。
十八、 HashCode和equal方法
equals反映的是對象或變量具體的值,即兩個(gè)對象包含的值(可能是對象的引用瀑志,可能是值類型的值)
hashcode是對象或者變量通過hash算法計(jì)算出來的值涩搓。
作用:
1??hashcode是用來提高M(jìn)ap的搜索效率,通過hashcode計(jì)算出放在哪個(gè)桶里劈猪,然后通過equals方法找出是否有重復(fù)的元素
2??想要正確的實(shí)現(xiàn)Map查找元素必須要滿足以下兩個(gè)條件:
1)兩個(gè)元素equals方法為true,則hashcode必定為true
2)兩個(gè)元素的hashcode為false,則equals方法必定為false
如果兩個(gè)元素的hashcode為true,再需要通過equals方法進(jìn)行比較
十九昧甘、進(jìn)程線程,安全問題
1)進(jìn)程和線程的區(qū)別?
進(jìn)程是一個(gè)獨(dú)立的運(yùn)行環(huán)境战得,可以看成一個(gè)程序或應(yīng)用充边,線程是進(jìn)程中的一個(gè)任務(wù)。
2)用戶線程和守護(hù)線程的區(qū)別?
在Java 程序中創(chuàng)建一個(gè)線程就是用戶線程,守護(hù)線程是java后臺(tái)提供的一種通用服務(wù)的線程浇冰,例如垃圾回收機(jī)制贬媒。守護(hù)線程不會(huì)阻止JVM的停止,只要還有一個(gè)用戶線程還在肘习,所有的守護(hù)線程都工作际乘,用戶線程停止工作,程序退出漂佩,則守護(hù)線程也退出了脖含。
3)如何創(chuàng)建一個(gè)線程?
一種是實(shí)現(xiàn)Runnable接口,把它傳遞給Thread的構(gòu)造函數(shù)投蝉,創(chuàng)建Thread對象
- ThreadLocal的作用养葵?
ThreadLocal并不是用來解決同步問題的,它只允許我們創(chuàng)建一個(gè)只能被同一線程訪問的變量瘩缆。如果一段代碼含有ThreadLocal关拒,即使有兩個(gè)線程訪問,也無法訪問到對方的ThreadLocal咳榜。例如JDBC中獲取Connection,把它與ThreadLocal進(jìn)行綁定夏醉,那么就不需要每次創(chuàng)建Connection,然是直接從ThreadLocal中讀出來涌韩。 - CAS樂觀鎖
樂觀鎖的核心是比較并交換畔柔,設(shè)計(jì)3個(gè)操作值:內(nèi)存值、預(yù)期值臣樱、新值靶擦,當(dāng)且僅當(dāng)預(yù)期值和內(nèi)存值想等時(shí)才會(huì)把內(nèi)存值更新為新值。
二十雇毫、volatile
禁止指令重排 可見線
會(huì)把volatile變量玄捕,會(huì)把線程所對應(yīng)的該變量內(nèi)存刷新到主內(nèi)存中。
1)第二個(gè)volatile變量寫棚放,第一個(gè)無論是什么操作枚粘,都不能進(jìn)行重排序
2)第一個(gè)volatile變量讀,第二個(gè)無論是什么操作飘蚯,都不能進(jìn)行重排序
3)第一個(gè)是volatile寫馍迄,第二個(gè)是volatile讀
這個(gè)三個(gè)規(guī)則構(gòu)成了兩個(gè)volatile變量操作不能進(jìn)行重排序
1、 對volatile變量執(zhí)行寫操作時(shí)局骤,會(huì)在寫操作后加入一條store屏障指令
2攀圈、 對volatile變量執(zhí)行讀操作時(shí),會(huì)在讀操作前加入一條load屏障指令峦甩。
通俗得講赘来,volatile變量在每次被線程訪問時(shí),都強(qiáng)迫從主內(nèi)存中讀該變量的值,而當(dāng)該變量發(fā)生變化時(shí)犬辰,又會(huì)強(qiáng)迫將最新的值刷新到主內(nèi)存嗦篱。這樣任何時(shí)刻,不同的線程總是能夠看到該變量的最新值幌缝。
二十一默色、多線程wait,notify, synchronized
wait方法使得當(dāng)前線程等待,必須等待另一個(gè)線程調(diào)用notify或notifyAll方法狮腿,當(dāng)前線程必須擁有該對象的鎖,這意味著wait方法必須放在synchronized代碼塊中
notify方法會(huì)喚醒一個(gè)等待當(dāng)前對象鎖的線程呕诉,notify應(yīng)該是被擁有對象鎖的線程所調(diào)用缘厢,同樣意味著notify方法也需要放在synchronized代碼塊中。
二十二甩挫、用戶線程與守護(hù)線程
守護(hù)線程就是程序在運(yùn)行過程中后臺(tái)提供的一種通用服務(wù)的線程贴硫,一般來說JVM 中有任意一個(gè)用戶線程存在,那么所有守護(hù)線程全部工作伊者,守護(hù)線程一個(gè)典型的案例就是垃圾回收機(jī)制英遭。
二十三、KMP算法
KMP算法的想法是亦渗,設(shè)法利用這個(gè)已知信息挖诸,不要把"搜索位置"移回已經(jīng)比較過的位置,只要繼續(xù)把它向后移和移動(dòng)匹配詞就可以法精,這樣就提高了效率多律。可以針對搜索詞搂蜓,算出一張部分匹配表狼荞。通過查表查到最后一個(gè)匹配字符對應(yīng)的部分匹配值,并利用以下公式計(jì)算匹配詞向后移動(dòng)的位數(shù):
移動(dòng)位數(shù) = 已匹配的字符數(shù) - 對應(yīng)的部分匹配值
二十四帮碰、Java NIO和IO
Java NIO和IO之間第一個(gè)最大的區(qū)別是相味,IO是面向流的,NIO是面向緩沖區(qū)的殉挽。 Java IO面向流意味著每次從流中讀一個(gè)或多個(gè)字節(jié)丰涉,直至讀取所有字節(jié),它們沒有被緩存在任何地方此再。此外昔搂,它不能前后移動(dòng)流中的數(shù)據(jù)。如果需要前后移動(dòng)從流中讀取的數(shù)據(jù)输拇,需要先將它緩存到一個(gè)緩沖區(qū)摘符。 Java NIO的緩沖導(dǎo)向方法略有不同。數(shù)據(jù)讀取到一個(gè)它稍后處理的緩沖區(qū),需要時(shí)可在緩沖區(qū)中前后移動(dòng)逛裤。這就增加了處理過程中的靈活性瘩绒。
Java IO的各種流是阻塞的。這意味著带族,當(dāng)一個(gè)線程調(diào)用read() 或 write()時(shí)锁荔,該線程被阻塞,直到有一些數(shù)據(jù)被讀取蝙砌,或數(shù)據(jù)完全寫入阳堕。該線程在此期間不能再干任何事情了。 Java NIO的非阻塞模式择克,使一個(gè)線程從某通道發(fā)送請求讀取數(shù)據(jù)恬总,但是它僅能得到目前可用的數(shù)據(jù),如果目前沒有數(shù)據(jù)可用時(shí)肚邢,就什么都不會(huì)獲取壹堰。
Java NIO的選擇器允許一個(gè)單獨(dú)的線程來監(jiān)視多個(gè)輸入通道,你可以注冊多個(gè)通道使用一個(gè)選擇器骡湖,然后使用一個(gè)單獨(dú)的線程來“選擇”通道
二十五贱纠、SQL優(yōu)化問題
1、 數(shù)據(jù)庫邏輯設(shè)計(jì)的規(guī)范化
1)沒有重復(fù)的組或多值的列响蕴,這是數(shù)據(jù)庫設(shè)計(jì)的最低要求
2)每個(gè)非關(guān)鍵字段必須依賴于主關(guān)鍵字谆焊,不能依賴于一個(gè)組合式主關(guān)鍵字的某些組成部分。消除部分依賴换途,大部分情況下懊渡,數(shù)據(jù)庫設(shè)計(jì)都應(yīng)該達(dá)到第二范式。
3)一個(gè)非關(guān)鍵字段不能依賴于另一個(gè)非關(guān)鍵字段军拟。
2剃执、 合理的冗余
1)
3、 主鍵的設(shè)計(jì)
主鍵是必要的懈息,SQL SERVER的主鍵同時(shí)是一個(gè)唯一索引肾档,而且在實(shí)際應(yīng)用中,我們往往選擇最小的鍵組合作為主鍵辫继,所以主鍵往往適合作為表的聚集索引怒见。聚集索引對查詢的影響是比較大的,這個(gè)在下面索引的敘述姑宽。
4遣耍、 外鍵的設(shè)計(jì)
外鍵是最高效的一致性維護(hù)方法,數(shù)據(jù)庫的一致性要求炮车,依次可以用外鍵舵变、CHECK約束酣溃、規(guī)則約束、觸發(fā)器纪隙、客戶端程序赊豌,一般認(rèn)為,離數(shù)據(jù)越近的方法效率越高绵咱。
5碘饼、 字段的設(shè)計(jì)
1)數(shù)據(jù)類型盡量用數(shù)字型,數(shù)字型的比較比字符型的快很多悲伶。
2) 數(shù)據(jù)類型盡量小艾恼,這里的盡量小是指在滿足可以預(yù)見的未來需求的前提下的。
3) 盡量不要允許NULL麸锉,除非必要蒂萎,可以用NOT NULL+DEFAULT代替。
4)少用TEXT和IMAGE淮椰,二進(jìn)制字段的讀寫是比較慢的,而且纳寂,讀取的方法也不多主穗,大部分情況下最好不用。
5) 自增字段要慎用毙芜,不利于數(shù)據(jù)遷移
注意事務(wù)和鎖
A忽媒、事務(wù)操作過程要盡量小,能拆分的事務(wù)要拆分開來腋粥。
B晦雨、 事務(wù)操作過程不應(yīng)該有交互,因?yàn)榻换サ却臅r(shí)候隘冲,事務(wù)并未結(jié)束闹瞧,可能鎖定了很多資源
C、 事務(wù)操作過程要按同一順序訪問對象展辞。
D奥邮、提高事務(wù)中每個(gè)語句的效率,利用索引和其他方法提高每個(gè)語句的效率可以有效地減少整個(gè)事務(wù)的執(zhí)行時(shí)間罗珍。
二十六 ReentrantLock
ReentrantLock 類實(shí)現(xiàn)了 Lock 洽腺,它擁有與 synchronized 相同的并發(fā)性和內(nèi)存語義,但是添加了類似鎖投票覆旱、定時(shí)鎖等候和可中斷鎖等候的一些特性蘸朋。
reentrant 鎖意味著什么呢?
簡單來說扣唱,它有一個(gè)與鎖相關(guān)的獲取計(jì)數(shù)器藕坯,如果擁有鎖的某個(gè)線程再次得到鎖团南,那么獲取計(jì)數(shù)器就加1,然后鎖需要被釋放兩次才能獲得真正釋放堕担。這模仿了 synchronized 的語義已慢;如果線程進(jìn)入由線程已經(jīng)擁有的監(jiān)控器保護(hù)的 synchronized 塊,就允許線程繼續(xù)進(jìn)行霹购,當(dāng)線程退出第二個(gè)(或者后續(xù)) synchronized 塊的時(shí)候佑惠,不釋放鎖,只有線程退出它進(jìn)入的監(jiān)控器保護(hù)的第一個(gè) synchronized 塊時(shí)齐疙,才釋放鎖膜楷。
相同:ReentrantLock提供了synchronized類似的功能和內(nèi)存語義。
不同:
(1)ReentrantLock功能性方面更全面贞奋,比如時(shí)間鎖等候赌厅,可中斷鎖等候,鎖投票等轿塔,因此更有擴(kuò)展性特愿。在多個(gè)條件變量和高度競爭鎖的地方,用ReentrantLock更合適勾缭,ReentrantLock還提供了Condition揍障,對線程的等待和喚醒等操作更加靈活,一個(gè)ReentrantLock可以有多個(gè)Condition實(shí)例俩由,所以更有擴(kuò)展性毒嫡。
(2)ReentrantLock 的性能比synchronized會(huì)好點(diǎn)。
(3)ReentrantLock提供了可輪詢的鎖請求幻梯,他可以嘗試的去取得鎖兜畸,如果取得成功則繼續(xù)處理,取得不成功碘梢,可以等下次運(yùn)行的時(shí)候處理咬摇,所以不容易產(chǎn)生死鎖,而synchronized則一旦進(jìn)入鎖請求要么成功煞躬,要么一直阻塞菲嘴,所以更容易產(chǎn)生死鎖。
Condition條件(也稱為條件隊(duì)列 或條件變量)為線程提供了一個(gè)含義汰翠,以便在某個(gè)狀態(tài)條件現(xiàn)在可能為 true 的另一個(gè)線程通知它之前龄坪,一直掛起該線程(即讓其“等待”)。因?yàn)樵L問此共享狀態(tài)信息發(fā)生在不同的線程中复唤,所以它必須受保護(hù)健田,因此要將某種形式的鎖與該條件相關(guān)聯(lián)。等待提供一個(gè)條件的主要屬性是:以原子方式 釋放相關(guān)的鎖佛纫,并掛起當(dāng)前線程妓局,就像 Object.wait 做的那樣总放。而且多個(gè)Condition需要綁定到同一鎖上。前面的Lock中提到好爬,獲取一個(gè)條件變量的方法是Lock.newCondition()局雄。
死鎖是兩個(gè)甚至多個(gè)線程被永久阻塞時(shí)的一種運(yùn)行局面,這種局面的生成伴隨著至少兩個(gè)線程和兩個(gè)或者多個(gè)資源存炮。在這里我已寫好一個(gè)簡單的程序炬搭,它將會(huì)引起死鎖方案然后我們就會(huì)明白如何分析它。
二十七 happens before
什么是happens-before關(guān)系穆桂? 這個(gè)關(guān)系其實(shí)就是一個(gè)保證而已宫盔,那么保證什么呢?它保證一條語句對內(nèi)存的寫操作對另一條語句是可見的享完。換句話說灼芭,如果寫操作A和讀操作B存在happens-before這種關(guān)系,那么寫操作在結(jié)束以后都操作才能開始般又。
下面是Java內(nèi)存模型中的八條可保證happen—before的規(guī)則彼绷,它們無需任何同步器協(xié)助就已經(jīng)存在,可以在編碼中直接使用茴迁。
1)程序次序規(guī)則:在一個(gè)單獨(dú)的線程中苛预,按照程序代碼的執(zhí)行流順序,(時(shí)間上)先執(zhí)行的操作happen—before(時(shí)間上)后執(zhí)行的操作笋熬。
2)管理鎖定規(guī)則:一個(gè)unlock操作happen—before后面(時(shí)間上的先后順序,下同)對同一個(gè)鎖的lock操作腻菇。
3)volatile變量規(guī)則:對一個(gè)volatile變量的寫操作happen—before后面對該變量的讀操作胳螟。
4)線程啟動(dòng)規(guī)則:Thread對象的start()方法happen—before此線程的每一個(gè)動(dòng)作。
5)線程終止規(guī)則:線程的所有操作都happen—before對此線程的終止檢測筹吐,可以通過Thread.join()方法結(jié)束糖耸、Thread.isAlive()的返回值等手段檢測到線程已經(jīng)終止執(zhí)行。
6)線程中斷規(guī)則:對線程interrupt()方法的調(diào)用happen—before發(fā)生于被中斷線程的代碼檢測到中斷時(shí)事件的發(fā)生丘薛。
7)對象終結(jié)規(guī)則:一個(gè)對象的初始化完成(構(gòu)造函數(shù)執(zhí)行結(jié)束)happen—before它的finalize()方法的開始嘉竟。
8)傳遞性:如果操作A happen—before操作B,操作B happen—before操作C洋侨,那么可以得出A happen—before操作C舍扰。
這里的八個(gè)規(guī)則除了第三個(gè)以外都容易理解。所以專門講一下volatile變量規(guī)則希坚。
1边苹、 對volatile變量執(zhí)行寫操作時(shí),會(huì)在寫操作后加入一條store屏障指令
2裁僧、 對volatile變量執(zhí)行讀操作時(shí)个束,會(huì)在讀操作前加入一條load屏障指令慕购。
通俗得講,volatile變量在每次被線程訪問時(shí)茬底,都強(qiáng)迫從主內(nèi)存中讀該變量的值沪悲,而當(dāng)該變量發(fā)生變化時(shí),又會(huì)強(qiáng)迫將最新的值刷新到主內(nèi)存阱表。這樣任何時(shí)刻殿如,不同的線程總是能夠看到該變量的最新值。
二十八 java所有單例模式
1捶枢、餓漢式(靜態(tài)常量)
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
2握截、餓漢式(靜態(tài)代碼塊)[可用]
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public Singleton getInstance() {
return instance;
}
}
3、懶漢式(線程不安全)[不可用]
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
4烂叔、懶漢式(線程安全谨胞,同步方法)[不推薦用]
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
5、懶漢式(線程安全蒜鸡,同步代碼塊)[不可用]
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
return singleton;
}
}
6胯努、雙重檢查[推薦用]
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
7、靜態(tài)內(nèi)部類[推薦用]
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
二十九 java線程池
newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池逢防,如果線程池長度超過處理需要叶沛,可靈活回收空閑線程,若無可回收忘朝,則新建線程灰署。
newFixedThreadPool 創(chuàng)建一個(gè)定長線程池,可控制線程最大并發(fā)數(shù)局嘁,超出的線程會(huì)在隊(duì)列中等待溉箕。
newScheduledThreadPool 創(chuàng)建一個(gè)定長線程池,支持定時(shí)及周期性任務(wù)執(zhí)行悦昵。
newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池肴茄,它只會(huì)用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行但指。
corePoolSize(線程池的基本大泄烟怠)
maximumPoolSize(線程池最大大小)
runnableTaskQueue(任務(wù)隊(duì)列)
1??ArrayBlockingQueue:是一個(gè)基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列棋凳,此隊(duì)列按 FIFO(先進(jìn)先出)
2??LinkedBlockingQueue:一個(gè)基于鏈表結(jié)構(gòu)的阻塞隊(duì)列拦坠,此隊(duì)列按FIFO (先進(jìn)先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue剩岳。
3??SynchronousQueue:一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列
RejectedExecutionHandler(飽和策略)
1??CallerRunsPolicy:只用調(diào)用者所在線程來運(yùn)行任務(wù)贪婉。
2??DiscardOldestPolicy:丟棄隊(duì)列里最近的一個(gè)任務(wù),并執(zhí)行當(dāng)前任務(wù)卢肃。
3??DiscardPolicy:不處理疲迂,丟棄掉才顿。