成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Java知識(shí)點(diǎn)總結(jié)

Lorry_Lu / 3587人閱讀

摘要:線(xiàn)程池中的和有什么不同直接提交的隊(duì)列該功能由對(duì)象提供。若大于最大線(xiàn)程數(shù),則執(zhí)行拒絕策略。因?yàn)閷?duì)于固定大小的線(xiàn)程池來(lái)說(shuō),不存在線(xiàn)程數(shù)量的動(dòng)態(tài)變化,所以最大線(xiàn)程數(shù)等于核心線(xiàn)程數(shù)。返回核心線(xiàn)程數(shù)為,最大線(xiàn)程數(shù)為無(wú)窮大的線(xiàn)程池。

索引的實(shí)現(xiàn)方式

1、B+樹(shù)

我們經(jīng)常聽(tīng)到B+樹(shù)就是這個(gè)概念,用這個(gè)樹(shù)的目的和紅黑樹(shù)差不多,也是為了盡量保持樹(shù)的平衡,當(dāng)然紅黑樹(shù)是二叉樹(shù),但B+樹(shù)就不是二叉樹(shù)了,節(jié)點(diǎn)下面可以有多個(gè)子節(jié)點(diǎn),數(shù)據(jù)庫(kù)開(kāi)發(fā)商會(huì)設(shè)置子節(jié)點(diǎn)數(shù)的一個(gè)最大值,這個(gè)值不會(huì)太小,所以B+樹(shù)一般來(lái)說(shuō)比較矮胖,而紅黑樹(shù)就比較瘦高了。

關(guān)于B+樹(shù)的插入,刪除,會(huì)涉及到一些算法以保持樹(shù)的平衡,這里就不詳述了。ORACLE的默認(rèn)索引就是這種結(jié)構(gòu)的。
如果經(jīng)常需要同時(shí)對(duì)兩個(gè)字段進(jìn)行AND查詢(xún),那么使用兩個(gè)多帶帶索引不如建立一個(gè)復(fù)合索引,因?yàn)閮蓚€(gè)多帶帶索引通常數(shù)據(jù)庫(kù)只能使用其中一個(gè),而使用復(fù)合索引因?yàn)樗饕旧砭蛯?duì)應(yīng)到兩個(gè)字段上的,效率會(huì)有很大提高。

2、散列索引

第二種索引叫做散列索引,就是通過(guò)散列函數(shù)來(lái)定位的一種索引,不過(guò)很少有多帶帶使用散列索引的,反而是散列文件組織用的比較多。

散列文件組織就是根據(jù)一個(gè)鍵通過(guò)散列計(jì)算把對(duì)應(yīng)的記錄都放到同一個(gè)槽中,這樣的話(huà)相同的鍵值對(duì)應(yīng)的記錄就一定是放在同一個(gè)文件里了,也就減少了文件讀取的次數(shù),提高了效率。
散列索引呢就是根據(jù)對(duì)應(yīng)鍵的散列碼來(lái)找到最終的索引項(xiàng)的技術(shù),其實(shí)和B樹(shù)就差不多了,也就是一種索引之上的二級(jí)輔助索引,我理解散列索引都是二級(jí)或更高級(jí)的稀疏索引,否則桶就太多了,效率也不會(huì)很高。

3、位圖索引

位圖索引是一種針對(duì)多個(gè)字段的簡(jiǎn)單查詢(xún)?cè)O(shè)計(jì)一種特殊的索引,適用范圍比較小,只適用于字段值固定并且值的種類(lèi)很少的情況,比如性別,只能有男和女,或者級(jí)別,狀態(tài)等等,并且只有在同時(shí)對(duì)多個(gè)這樣的字段查詢(xún)時(shí)才能體現(xiàn)出位圖的優(yōu)勢(shì)。

位圖的基本思想就是對(duì)每一個(gè)條件都用0或者1來(lái)表示,如有5條記錄,性別分別是男,女,男,男,女,那么如果使用位圖索引就會(huì)建立兩個(gè)位圖,對(duì)應(yīng)男的10110和對(duì)應(yīng)女的01001,這樣做有什么好處呢,就是如果同時(shí)對(duì)多個(gè)這種類(lèi)型的字段進(jìn)行and或or查詢(xún)時(shí),可以使用按位與和按位或來(lái)直接得到結(jié)果了。

為了進(jìn)一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個(gè)索引里:

ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age); 

建表時(shí),usernname長(zhǎng)度為 16,這里用 10。這是因?yàn)橐话闱闆r下名字的長(zhǎng)度不會(huì)超過(guò)10,這樣會(huì)加速索引查詢(xún)速度,還會(huì)減少索引文件的大小,提高INSERT的更新速度。

如果分別在 usernname,city,age上建立單列索引,讓該表有3個(gè)單列索引,查詢(xún)時(shí)和上述的組合索引效率也會(huì)大不一樣,遠(yuǎn)遠(yuǎn)低于我們的組合索引。雖然此時(shí)有了三個(gè)索引,但MySQL只能用到其中的那個(gè)它認(rèn)為似乎是最有效率的單列索引。

建立這樣的組合索引,其實(shí)是相當(dāng)于分別建立了下面三組組合MySQL數(shù)據(jù)庫(kù)索引:

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );

usernname,city,age usernname,city usernname 為什么沒(méi)有 city,age這樣的組合索引呢?這是因?yàn)镸ySQL組合索引“最左前綴”的結(jié)果。簡(jiǎn)單的理解就是只從最左面的開(kāi)始組合。并不是只要包含這三列的查詢(xún)都會(huì)用到該組合索引,下面的幾個(gè)SQL就會(huì)用到這個(gè)組合MySQL數(shù)據(jù)庫(kù)索引:

SELECT * FROM mytable WHREE username="admin" AND city="鄭州" SELECT * FROM mytable WHREE username="admin"

而下面幾個(gè)則不會(huì)用到:

SELECT * FROM mytable WHREE age=20 AND city="鄭州" SELECT * FROM mytable WHREE city="鄭州"

使用索引的代價(jià)

1、索引需要占用數(shù)據(jù)表以外的物理存儲(chǔ)空間
2、創(chuàng)建索引和維護(hù)索引要花費(fèi)一定的時(shí)間
3、當(dāng)對(duì)表進(jìn)行更新操作時(shí),索引需要被重建,這樣降低了數(shù)據(jù)的維護(hù)速度

什么情況下不適合建立索引?

1.對(duì)于在查詢(xún)過(guò)程中很少使用或參考的列,不應(yīng)該創(chuàng)建索引。
2.對(duì)于那些只有很少數(shù)據(jù)值的列,不應(yīng)該創(chuàng)建索引。
3.對(duì)于那些定義為image,text和bit數(shù)據(jù)類(lèi)型的列,不應(yīng)該創(chuàng)建索引。
4.當(dāng)修改性能遠(yuǎn)大于檢索性能,不應(yīng)該建立索引。


線(xiàn)程池中的corenum和maxnum有什么不同?

(1) 直接提交的隊(duì)列:該功能由SynchronizedQueue對(duì)象提供。SynchronizedQueue是一個(gè)特殊的阻塞隊(duì)列。SynchronizedQueue沒(méi)有容量,每一個(gè)插入操作都要等待一個(gè)相應(yīng)的刪除操作,反之每一個(gè)刪除操作都需要等待對(duì)應(yīng)的插入操作。使用SynchronizedQueue時(shí)提交的任務(wù)不會(huì)被真實(shí)的保存,而總是將新任務(wù)提交給線(xiàn)程執(zhí)行,如果沒(méi)有空閑的線(xiàn)程則嘗試創(chuàng)建新的線(xiàn)程,如果線(xiàn)程數(shù)量達(dá)到最大值就執(zhí)行決絕策略。使用SynchronizedQueue隊(duì)列通常要設(shè)置很大的maxnumPoolSize,否則很容易執(zhí)行拒絕策略??梢援?dāng)做大小為0的隊(duì)列來(lái)理解。

(2) 有界的任務(wù)隊(duì)列:有界的任務(wù)隊(duì)列可以使用ArrayBlockingQueue實(shí)現(xiàn)。當(dāng)使用有界的任務(wù)隊(duì)列時(shí),若有新的任務(wù)需要執(zhí)行,如果線(xiàn)程池的實(shí)際線(xiàn)程數(shù)小于核心線(xiàn)程數(shù),則有優(yōu)先創(chuàng)建新的線(xiàn)程,若大于核心線(xiàn)程數(shù),則會(huì)將新任務(wù)加入等待隊(duì)列。若隊(duì)列已滿(mǎn),無(wú)法加入則在總線(xiàn)程數(shù)不大于最大線(xiàn)程數(shù)的前提下,創(chuàng)建新的線(xiàn)程。若大于最大線(xiàn)程數(shù),則執(zhí)行拒絕策略。也就是說(shuō),有界隊(duì)列僅當(dāng)任務(wù)隊(duì)列滿(mǎn)時(shí)才可能將線(xiàn)程數(shù)提升到核心線(xiàn)程數(shù)只上,否則確保線(xiàn)程數(shù)維持在核心線(xiàn)程數(shù)大小。

(3) 無(wú)界任務(wù)隊(duì)列:無(wú)界任務(wù)隊(duì)列可以通過(guò)LinkedBlockingQueue類(lèi)來(lái)實(shí)現(xiàn)。與有界隊(duì)列相比,除非系統(tǒng)資源耗盡,否則無(wú)界隊(duì)列不存在任務(wù)入隊(duì)失敗的情況。當(dāng)有新的任務(wù)到來(lái),系統(tǒng)的線(xiàn)程數(shù)小于核心線(xiàn)程數(shù)時(shí)線(xiàn)程池會(huì)生成新的線(xiàn)程執(zhí)行任務(wù),但當(dāng)系統(tǒng)線(xiàn)程數(shù)大于核心線(xiàn)程數(shù)后,就不會(huì)繼續(xù)增加。若后續(xù)有新的任務(wù),則將任務(wù)放入無(wú)界隊(duì)列中等待。

(4) 優(yōu)先任務(wù)隊(duì)列:優(yōu)先任務(wù)隊(duì)列是帶有執(zhí)行優(yōu)先級(jí)的隊(duì)列,通過(guò)PriorityBlockingQueue實(shí)現(xiàn),可以控制任務(wù)的執(zhí)行先后順序,是一個(gè)特殊的無(wú)界隊(duì)列。無(wú)論是有界隊(duì)列還ArrayBlockingQueue還是未指定大小的無(wú)界隊(duì)列LinkedBlockingQueue,都是按照先進(jìn)先出算法處理任務(wù)的,而有限隊(duì)列則可以根據(jù)任務(wù)自身的優(yōu)先級(jí)順序執(zhí)行,在確保系統(tǒng)性能的同時(shí),也能有很好的質(zhì)量保證。

回過(guò)頭看Executor框架提供了幾種線(xiàn)程池,newFixedThreadPool()返回的固定大小線(xiàn)程池中核心線(xiàn)程數(shù)和最大線(xiàn)程數(shù)一樣,并且使用了無(wú)界隊(duì)列。因?yàn)閷?duì)于固定大小的線(xiàn)程池來(lái)說(shuō),不存在線(xiàn)程數(shù)量的動(dòng)態(tài)變化,所以最大線(xiàn)程數(shù)等于核心線(xiàn)程數(shù)。同時(shí),使用無(wú)界隊(duì)列存放無(wú)法立即執(zhí)行的任務(wù),當(dāng)任務(wù)提交非常頻繁時(shí),隊(duì)列可能迅速膨脹,從而耗盡系統(tǒng)資源。

newSingleThreadExecutor()返回的單線(xiàn)程線(xiàn)程池,是固定大小線(xiàn)程池的一種退化,只是簡(jiǎn)單的將線(xiàn)程池?cái)?shù)量設(shè)置為1。
newCachedThreadExecutor()返回核心線(xiàn)程數(shù)為0,最大線(xiàn)程數(shù)為無(wú)窮大的線(xiàn)程池。使用直接提交隊(duì)列SynchronizedQueue。
當(dāng)Executor提供的線(xiàn)程池不滿(mǎn)足使用場(chǎng)景時(shí),則需要使用自定義線(xiàn)程池,選擇合適的任務(wù)隊(duì)列來(lái)作為緩沖。不同的并發(fā)隊(duì)列對(duì)系統(tǒng)和性能的影響均不同。


如何找出單鏈表中的倒數(shù)第k個(gè)元素?

思路一:
初看題目,最容易想到的方法就是遍歷。首先遍歷一遍單鏈表,得出整個(gè)鏈表的長(zhǎng)度n(元素個(gè)數(shù)從1到n),然后找到倒數(shù)第k個(gè)元素的位置n-k+1,接著從頭遍歷到第n-k+1元素,就是倒數(shù)第k個(gè)元素。但是該方法需要對(duì)鏈表進(jìn)行兩次遍歷,遍歷的元素個(gè)數(shù)為n+n-k+1=2n+1-k個(gè)。

思路二:
有了思路一的提示,是不是可以想到用兩個(gè)指針,讓它們之間的距離保持為k-1,同時(shí)對(duì)鏈表進(jìn)行遍歷,當(dāng)?shù)谝粋€(gè)指針到達(dá)鏈表的最后一個(gè)元素(即倒數(shù)第一個(gè)元素時(shí)),第二個(gè)指針剛好停留在倒數(shù)第k個(gè)元素上。此方法看似對(duì)鏈表進(jìn)行了一次遍歷,其實(shí)是用兩個(gè)指針對(duì)鏈表進(jìn)行了同時(shí)遍歷,對(duì)鏈表本身而言,它被遍歷的元素個(gè)數(shù)仍是n+n-k+1=2n+1-k個(gè)。

思路三:
思路一和思路二是兩種不同思路,但就本質(zhì)而言,都是兩次對(duì)鏈表進(jìn)行2次遍歷,一次遍歷n個(gè)元素,另一次遍歷n-k+1個(gè),總共遍歷2n+1-k個(gè)元素。此時(shí),想想能否再減少遍歷的元素個(gè)數(shù)而找到倒數(shù)第k個(gè)元素呢?我們注意到思路二,是用兩個(gè)指針,保持k-1個(gè)元素的距離同時(shí)進(jìn)行遍歷的,可否按著每次k個(gè)元素這樣的遍歷下去呢。這樣遍歷的結(jié)果就是,每次遍歷k個(gè)元素,遍歷m次(m=n/k),最后一次遍歷的個(gè)數(shù)為i個(gè)(i=n%k),我們只需記錄最后一次遍歷k個(gè)元素的起始位置,然后再遍歷i個(gè)元素,此時(shí)的位置即為倒數(shù)第k個(gè)元素。此時(shí),對(duì)鏈表遍歷的元素個(gè)數(shù)為n+i(i為n除以k的余數(shù))。


多線(xiàn)程缺點(diǎn)?

1、將給定的工作量劃分給過(guò)多的線(xiàn)程會(huì)造成每個(gè)線(xiàn)程的工作量過(guò)少,因此可能導(dǎo)致線(xiàn)程啟動(dòng)和終止時(shí)的開(kāi)銷(xiāo)比程序?qū)嶋H工作的開(kāi)銷(xiāo)還要多;

2、過(guò)多并發(fā)線(xiàn)程的存在將導(dǎo)致共享有限硬件資源的開(kāi)銷(xiāo)增大。

線(xiàn)程相對(duì)于進(jìn)程的優(yōu)點(diǎn):
1、開(kāi)銷(xiāo)小
2、資源共享性好。

線(xiàn)程相對(duì)于進(jìn)程的缺點(diǎn):
1、共享資源需要耗費(fèi)一定的鎖資源,同步相對(duì)復(fù)雜。
2、一個(gè)線(xiàn)程崩潰可能導(dǎo)致整個(gè)進(jìn)程崩潰,這個(gè)當(dāng)然是自己的應(yīng)用程序有問(wèn)題


迭代和遞歸的最大區(qū)別是?

遞歸與迭代都是基于控制結(jié)構(gòu):迭代用重復(fù)結(jié)構(gòu),而遞歸用選擇結(jié)構(gòu)。

遞歸與迭代都涉及重復(fù):迭代顯式使用重復(fù)結(jié)構(gòu),而遞歸通過(guò)重復(fù)函數(shù)調(diào)用實(shí)現(xiàn)重復(fù)。

遞歸與迭代都涉及終止測(cè)試:迭代在循環(huán)條件失敗時(shí)終止,遞歸在遇到基本情況時(shí)終止。

使用計(jì)數(shù)器控制重復(fù)的迭代和遞歸都逐漸到達(dá)終止點(diǎn):迭代一直修改計(jì)數(shù)器,直到計(jì)數(shù)器值使循環(huán)條件失??;遞歸不斷產(chǎn)生最初問(wèn)題的簡(jiǎn)化副本,直到達(dá)到基本情況。迭代和遞歸過(guò)程都可以無(wú)限進(jìn)行:如果循環(huán)條件測(cè)試永遠(yuǎn)不變成false,則迭代發(fā)生無(wú)限循環(huán);如果遞歸永遠(yuǎn)無(wú)法回推到基本情況,則發(fā)生無(wú)窮遞歸。
遞歸函數(shù)是通過(guò)調(diào)用函數(shù)自身來(lái)完成任務(wù),而且在每次調(diào)用自身時(shí)減少任務(wù)量。而迭代是循環(huán)的一種形式,這種循環(huán)不是由用戶(hù)輸入而控制,每次迭代步驟都必須將剩余的任務(wù)減少;也就是說(shuō),循環(huán)的每一步都必須執(zhí)行一個(gè)有限的過(guò)程,并留下較少的步驟。


SQL truncate 、delete與drop區(qū)別?

相同點(diǎn):

1.truncate和不帶where子句的delete、以及drop都會(huì)刪除表內(nèi)的數(shù)據(jù)。

2.drop、truncate都是DDL語(yǔ)句(數(shù)據(jù)定義語(yǔ)言),執(zhí)行后會(huì)自動(dòng)提交。

不同點(diǎn):

truncate 和 delete 只刪除數(shù)據(jù)不刪除表的結(jié)構(gòu)(定義)

語(yǔ)句將刪除表的結(jié)構(gòu)被依賴(lài)的約束(constrain)、觸發(fā)器(trigger)、索引(index);依賴(lài)于該表的存儲(chǔ)過(guò)程/函數(shù)將保留,但是變?yōu)?invalid 狀態(tài)。

delete 語(yǔ)句是數(shù)據(jù)庫(kù)操作語(yǔ)言(dml),這個(gè)操作會(huì)放到 rollback segement 中,事務(wù)提交之后才生效;如果有相應(yīng)的 trigger,執(zhí)行的時(shí)候?qū)⒈挥|發(fā)。

truncate、drop 是數(shù)據(jù)庫(kù)定義語(yǔ)言(ddl),操作立即生效,原數(shù)據(jù)不放到 rollback segment 中,不能回滾,操作不觸發(fā) trigger。

3.delete 語(yǔ)句不影響表所占用的 extent,高水線(xiàn)(high watermark)保持原位置不動(dòng)
drop 語(yǔ)句將表所占用的空間全部釋放。
truncate 語(yǔ)句缺省情況下見(jiàn)空間釋放到 minextents個(gè) extent,除非使用reuse storage;truncate 會(huì)將高水線(xiàn)復(fù)位(回到最開(kāi)始)。

4.速度,一般來(lái)說(shuō): drop> truncate > delete

5.安全性:小心使用 drop 和 truncate,尤其沒(méi)有備份的時(shí)候.否則哭都來(lái)不及
使用上,想刪除部分?jǐn)?shù)據(jù)行用 delete,注意帶上where子句. 回滾段要足夠大.
想刪除表,當(dāng)然用 drop;
想保留表而將所有數(shù)據(jù)刪除,如果和事務(wù)無(wú)關(guān),用truncate即可。如果和事務(wù)有關(guān),或者想觸發(fā)trigger,還是用delete。
如果是整理表內(nèi)部的碎片,可以用truncate跟上reuse stroage,再重新導(dǎo)入/插入數(shù)據(jù)。

6.delete是DML語(yǔ)句,不會(huì)自動(dòng)提交。drop/truncate都是DDL語(yǔ)句,執(zhí)行后會(huì)自動(dòng)提交。

7、TRUNCATE TABLE 在功能上與不帶 WHERE 子句的 DELETE 語(yǔ)句相同:二者均刪除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統(tǒng)和事務(wù)日志資源少。DELETE 語(yǔ)句每次刪除一行,并在事務(wù)日志中為所刪除的每行記錄一項(xiàng)。TRUNCATE TABLE 通過(guò)釋放存儲(chǔ)表數(shù)據(jù)所用的數(shù)據(jù)頁(yè)來(lái)刪除數(shù)據(jù),并且只在事務(wù)日志中記錄頁(yè)的釋放。

8、TRUNCATE TABLE 刪除表中的所有行,但表結(jié)構(gòu)及其列、約束、索引等保持不變。新行標(biāo)識(shí)所用的計(jì)數(shù)值重置為該列的種子。如果想保留標(biāo)識(shí)計(jì)數(shù)值,請(qǐng)改用 DELETE。如果要?jiǎng)h除表定義及其數(shù)據(jù),請(qǐng)使用 DROP TABLE 語(yǔ)句。

9、對(duì)于由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應(yīng)使用不帶 WHERE 子句的 DELETE 語(yǔ)句。由于 TRUNCATE TABLE 不記錄在日志中,所以它不能激活觸發(fā)器。

10、TRUNCATE TABLE 不能用于參與了索引視圖的表。


總結(jié)常見(jiàn)的mysql數(shù)據(jù)庫(kù)優(yōu)化操作?

1、Index索引

2、少用SELECT *

可能有的人查詢(xún)數(shù)據(jù)庫(kù)時(shí),遇到要查詢(xún)的都會(huì)select,這是不恰當(dāng)?shù)男袨?。我們?yīng)該取我們要用的數(shù)據(jù),而不是全取,因?yàn)楫?dāng)我們select時(shí),會(huì)增加web服務(wù)器的負(fù)擔(dān),增加網(wǎng)絡(luò)傳輸?shù)呢?fù)載,查詢(xún)速度自然就下降 。

3、開(kāi)啟查詢(xún)緩存

大多數(shù)的MySQL服務(wù)器都開(kāi)啟了查詢(xún)緩存。這是提高性最有效的方法之一,而且這是被MySQL的數(shù)據(jù)庫(kù)引擎處理的。當(dāng)有很多相同的查詢(xún)被執(zhí)行了多次的時(shí)候,這些查詢(xún)結(jié)果會(huì)被放到一個(gè)緩存中,這樣,后續(xù)的相同的查詢(xún)就不用操作表而直接訪(fǎng)問(wèn)緩存結(jié)果了。

4、使用NOT NULL

  很多表都包含可為NULL(空值)的列,即使應(yīng)用程序并不需要保存 NULL 也是如此 ,這是因?yàn)榭蔀镹ULL是列的默認(rèn)屬性。通常情況下最好指定列為 NOT NULL,除非真的需要存儲(chǔ)NULL值。如果查詢(xún)中包含可為NULL的列,對(duì) MySQL 來(lái)說(shuō)更難優(yōu)化 ,因?yàn)榭蔀?NULL 的列使 得索引、索引統(tǒng)計(jì)和值比較都更復(fù)雜 ??蔀镹ULL 的列會(huì)使用更多的存儲(chǔ)空間 ,在MySQL里也需要特殊處理 。當(dāng)可為NULL 的列被索引肘,每個(gè)索引記錄需要一個(gè)額 外的字節(jié),在 MyISAM 里甚至還可能導(dǎo)致固定大小 的索引 (例如只有一個(gè)整數(shù)列的 索引) 變成可變大小的索引。

  通常把可為 NULL 的列改為 NOT NULL 帶來(lái)的性能提升比較小 ,所以 (調(diào)優(yōu)時(shí)) 沒(méi)有 必要首先在現(xiàn)有schema中查找井修改掉這種情況 ,除非確定這會(huì)導(dǎo)致問(wèn)題。但是, 如果計(jì)劃在列上建索引 ,就應(yīng)該盡量避免設(shè)計(jì)成可為 NULL 的列。當(dāng)然也有例外 ,例如值得一提的是,InnoDB 使用多帶帶的位 (bit ) 存儲(chǔ) NULL 值 ,所 以對(duì)于稀疏數(shù)據(jù)由有很好的空間效率 。但這一點(diǎn)不適用于MyISAM 。

5、避免在 where 子句中使用 or 來(lái)連接

如果一個(gè)字段有索引,一個(gè)字段沒(méi)有索引,將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:

select id from t where num=10 or Name = "admin"

可以這樣查詢(xún):

select id from t where num = 10
union all
select id from t where Name = "admin"

6、多使用varchar/nvarchar

使用varchar/nvarchar代替 char/nchar ,因?yàn)槭紫茸冮L(zhǎng)字段存儲(chǔ)空間小,可以節(jié)省存儲(chǔ)空間,其次對(duì)于查詢(xún)來(lái)說(shuō),在一個(gè)相對(duì)較小的字段內(nèi)搜索效率顯然要高些。

7、避免大數(shù)據(jù)量返回

這里要考慮使用limit,來(lái)限制返回的數(shù)據(jù)量,如果每次返回大量自己不需要的數(shù)據(jù),也會(huì)降低查詢(xún)速度。

8、where子句優(yōu)化

where 子句中使用參數(shù),會(huì)導(dǎo)致全表掃描,因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪(fǎng)問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然 而,如果在編譯時(shí)建立訪(fǎng)問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。
應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,避免在where子句中對(duì)字段進(jìn)行函數(shù)操作這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。


SQL語(yǔ)句中executeQuery、executeUpdate、execute的區(qū)別?

ResultSet executeQuery(String sql); 執(zhí)行SQL查詢(xún),并返回ResultSet 對(duì)象。

int executeUpdate(String sql); 可執(zhí)行增,刪,改,返回執(zhí)行受到影響的行數(shù)。

boolean execute(String sql); 可執(zhí)行任何SQL語(yǔ)句,返回一個(gè)布爾值,表示是否返回ResultSet 。

execute是executeQuery和executeUpdate的綜合.

executeUpdate() 這是 PreparedStatement 接口中的方法
executeUpdate(String sql) 這是 PreparedStatement 從父接口 Statement 中繼承過(guò)來(lái)的方法

executeUpdate() 中執(zhí)行 SQL 語(yǔ)句需要在創(chuàng)建 PerparedStatement 時(shí)通過(guò) Connection 的 prepareStatement(String sql) 方法中寫(xiě)出,因?yàn)?PerparedStatement 中的 SQL 語(yǔ)句數(shù)據(jù)庫(kù)需要進(jìn)行預(yù)編譯和緩存,因此要在創(chuàng)建 PerparedStatement 對(duì)象時(shí)給出 SQL 語(yǔ)句。

而 executeUpdate(String sql) 是 Statement 中的方法,參數(shù)中的 SQL 語(yǔ)句只是提交給數(shù)據(jù)庫(kù)去執(zhí)行,并不需要預(yù)編譯。

如果 SQL 語(yǔ)句中有 ? 占位符,那么在設(shè)置好占位符中的值后,必須使用 executeUpdate() 執(zhí)行。而 executeUpdate(String sql) 只是提交一個(gè) SQL 語(yǔ)句,且這個(gè)語(yǔ)句中不能帶有 ? 占位符。

1、在Java中如何使用execute()、executeQuery()、executeUpdate()三個(gè)方法?
execute(String sql)

      執(zhí)行給定的 SQL 語(yǔ)句,該語(yǔ)句可能返回多個(gè)結(jié)果。

executeQuery(String sql)

      執(zhí)行給定的 SQL 語(yǔ)句,該語(yǔ)句返回單個(gè) ResultSet 對(duì)象

executeUpdate(String sql)

      執(zhí)行給定 SQL 語(yǔ)句,該語(yǔ)句可能為 INSERT、UPDATE 或 DELETE 語(yǔ)句,或者不返回任何內(nèi)容的 SQL 語(yǔ)句(如 SQL DDL 語(yǔ)句)

頭2種一般在查詢(xún)中使用

最后一個(gè)在插入、更新、刪除時(shí)使用

2、executeQuery()是干什么用的?實(shí)現(xiàn)什么功能啊?
使用JDBC連接數(shù)據(jù)庫(kù)需要四步,第一步加載驅(qū)動(dòng)程序;第二步,連接數(shù)據(jù)庫(kù);第三步,訪(fǎng)問(wèn)數(shù)據(jù)庫(kù);第四步,執(zhí)行查詢(xún);其中在第四步執(zhí)行查詢(xún)時(shí),要用statement類(lèi)的executeQuery()方法來(lái)下達(dá)select指令以查詢(xún)數(shù)據(jù)庫(kù),executeQuery()方法會(huì)把數(shù)據(jù)庫(kù)響應(yīng)的查詢(xún)結(jié)果存放在ResultSet類(lèi)對(duì)象中供我們使用。即語(yǔ)句:String sql="select * from"+tableName; ResultSet rs=s.executeQuery(sql);

3、executeQuery、executeUpdate或execute方法區(qū)別?
在用純JSP做一個(gè)頁(yè)面報(bào)警功能的時(shí)候習(xí)慣性的用executeQuery來(lái)執(zhí)行SQL語(yǔ)句,結(jié)果執(zhí)行update時(shí)就遇到問(wèn)題,語(yǔ)句能執(zhí)行,但返回結(jié)果出現(xiàn)問(wèn)題,另外還忽略了executeUpdate的返回值不是結(jié)果集ResultSet,而是數(shù)值!特收藏如下一篇文章(感謝網(wǎng)友們對(duì)各種信息的貢獻(xiàn)):

JDBCTM中Statement接口提供的execute、executeQuery和executeUpdate之間的區(qū)別

Statement 接口提供了三種執(zhí)行 SQL 語(yǔ)句的方法:executeQuery、executeUpdate 和 execute。使用哪一個(gè)方法由 SQL 語(yǔ)句所產(chǎn)生的內(nèi)容決定。

方法executeQuery
用于產(chǎn)生單個(gè)結(jié)果集的語(yǔ)句,例如 SELECT 語(yǔ)句。 被使用最多的執(zhí)行 SQL 語(yǔ)句的方法是 executeQuery。這個(gè)方法被用來(lái)執(zhí)行 SELECT 語(yǔ)句,它幾乎是使用最多的 SQL 語(yǔ)句。

方法executeUpdate
用于執(zhí)行 INSERT、UPDATE 或 DELETE 語(yǔ)句以及 SQL DDL(數(shù)據(jù)定義語(yǔ)言)語(yǔ)句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 語(yǔ)句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一個(gè)整數(shù),指示受影響的行數(shù)(即更新計(jì)數(shù))。對(duì)于 CREATE TABLE 或 DROP TABLE 等不操作行的語(yǔ)句,executeUpdate 的返回值總為零。

使用executeUpdate方法是因?yàn)樵?createTableCoffees 中的 SQL 語(yǔ)句是 DDL (數(shù)據(jù)定義語(yǔ)言)語(yǔ)句。創(chuàng)建表,改變表,刪除表都是 DDL 語(yǔ)句的例子,要用 executeUpdate 方法來(lái)執(zhí)行。你也可以從它的名字里看出,方法 executeUpdate 也被用于執(zhí)行更新表 SQL 語(yǔ)句。實(shí)際上,相對(duì)于創(chuàng)建表來(lái)說(shuō),executeUpdate 用于更新表的時(shí)間更多,因?yàn)楸碇恍枰獎(jiǎng)?chuàng)建一次,但經(jīng)常被更新。

方法execute:
用于執(zhí)行返回多個(gè)結(jié)果集、多個(gè)更新計(jì)數(shù)或二者組合的語(yǔ)句。因?yàn)槎鄶?shù)程序員不會(huì)需要該高級(jí)功能

execute方法應(yīng)該僅在語(yǔ)句能返回多個(gè)ResultSet對(duì)象、多個(gè)更新計(jì)數(shù)或ResultSet對(duì)象與更新計(jì)數(shù)的組合時(shí)使用。當(dāng)執(zhí)行某個(gè)已存儲(chǔ)過(guò)程 或動(dòng)態(tài)執(zhí)行未知 SQL 字符串(即應(yīng)用程序程序員在編譯時(shí)未知)時(shí),有可能出現(xiàn)多個(gè)結(jié)果的情況,盡管這種情況很少見(jiàn)。
因?yàn)榉椒?execute 處理非常規(guī)情況,所以獲取其結(jié)果需要一些特殊處理并不足為怪。例如,假定已知某個(gè)過(guò)程返回兩個(gè)結(jié)果集,則在使用方法 execute 執(zhí)行該過(guò)程后,必須調(diào)用方法 getResultSet 獲得第一個(gè)結(jié)果集,然后調(diào)用適當(dāng)?shù)?getXXX 方法獲取其中的值。要獲得第二個(gè)結(jié)果集,需要先調(diào)用 getMoreResults 方法,然后再調(diào)用 getResultSet 方法。如果已知某個(gè)過(guò)程返回兩個(gè)更新計(jì)數(shù),則首先調(diào)用方法 getUpdateCount,然后調(diào)用 getMoreResults,并再次調(diào)用 getUpdateCount。
對(duì)于不知道返回內(nèi)容,則情況更為復(fù)雜。如果結(jié)果是 ResultSet 對(duì)象,則方法 execute 返回 true;如果結(jié)果是 Java int,則返回 false。如果返回 int,則意味著結(jié)果是更新計(jì)數(shù)或執(zhí)行的語(yǔ)句是 DDL 命令。在調(diào)用方法 execute 之后要做的第一件事情是調(diào)用 getResultSet 或 getUpdateCount。調(diào)用方法 getResultSet 可以獲得兩個(gè)或多個(gè) ResultSet 對(duì)象中第一個(gè)對(duì)象;或調(diào)用方法 getUpdateCount 可以獲得兩個(gè)或多個(gè)更新計(jì)數(shù)中第一個(gè)更新計(jì)數(shù)的內(nèi)容。
當(dāng) SQL 語(yǔ)句的結(jié)果不是結(jié)果集時(shí),則方法 getResultSet 將返回 null。這可能意味著結(jié)果是一個(gè)更新計(jì)數(shù)或沒(méi)有其它結(jié)果。在這種情況下,判斷 null 真正含義的唯一方法是調(diào)用方法 getUpdateCount,它將返回一個(gè)整數(shù)。這個(gè)整數(shù)為調(diào)用語(yǔ)句所影響的行數(shù);如果為 -1 則表示結(jié)果是結(jié)果集或沒(méi)有結(jié)果。如果方法 getResultSet 已返回 null(表示結(jié)果不是 ResultSet 對(duì)象),則返回值 -1 表示沒(méi)有其它結(jié)果。也就是說(shuō),當(dāng)下列條件為真時(shí)表示沒(méi)有結(jié)果(或沒(méi)有其它結(jié)果):

((stmt.getResultSet() == null) && (stmt.getUpdateCount() == -1))

如果已經(jīng)調(diào)用方法 getResultSet 并處理了它返回的 ResultSet 對(duì)象,則有必要調(diào)用方法 getMoreResults 以確定是否有其它結(jié)果集或更新計(jì)數(shù)。如果 getMoreResults 返回 true,則需要再次調(diào)用 getResultSet 來(lái)檢索下一個(gè)結(jié)果集。如上所述,如果 getResultSet 返回 null,則需要調(diào)用 getUpdateCount 來(lái)檢查 null 是表示結(jié)果為更新計(jì)數(shù)還是表示沒(méi)有其它結(jié)果。

當(dāng) getMoreResults 返回 false 時(shí),它表示該 SQL 語(yǔ)句返回一個(gè)更新計(jì)數(shù)或沒(méi)有其它結(jié)果。因此需要調(diào)用方法 getUpdateCount 來(lái)檢查它是哪一種情況。在這種情況下,當(dāng)下列條件為真時(shí)表示沒(méi)有其它結(jié)果:

((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))

下面的代碼演示了一種方法用來(lái)確認(rèn)已訪(fǎng)問(wèn)調(diào)用方法 execute 所產(chǎn)生的全部結(jié)果集和更新計(jì)數(shù):

stmt.execute(queryStringWithUnknownResults);
while (true) {
int rowCount = stmt.getUpdateCount();
if (rowCount > 0) { // 它是更新計(jì)數(shù)
System.out.println("Rows changed = " + count);
stmt.getMoreResults();


Spring初始化過(guò)程?

  在傳統(tǒng)的Java應(yīng)用中,Bean的生命周期非常簡(jiǎn)單。Java的關(guān)鍵詞new用來(lái)實(shí)例化Bean(或許他是非序列化的)。這樣就夠用了。相反,Bean 的生命周期在spring容器中更加細(xì)致。理解Spring Bean的生命周期非常重要,因?yàn)槟慊蛟S要利用Spring提供的機(jī)會(huì)來(lái)訂制Bean的創(chuàng)建過(guò)程。

1.容器尋找Bean的定義信息并且將其實(shí)例化。

2.使用依賴(lài)注入,Spring按照Bean定義信息配置Bean的所有屬性。

3.如果Bean實(shí)現(xiàn)了BeanNameAware接口,工廠(chǎng)調(diào)用Bean的setBeanName()方法傳遞Bean的ID。

4.如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,工廠(chǎng)調(diào)用setBeanFactory()方法傳入工廠(chǎng)自身。

5.如果BeanPostProcessor和Bean關(guān)聯(lián),那么它們的postProcessBeforeInitialzation()方法將被調(diào)用。

6.如果Bean指定了init-method方法,它將被調(diào)用。

7.最后,如果有BeanPsotProcessor和Bean關(guān)聯(lián),那么它們的postProcessAfterInitialization()方法將被調(diào)用。

  到這個(gè)時(shí)候,Bean已經(jīng)可以被應(yīng)用系統(tǒng)使用了,并且將被保留在Bean Factory中知道它不再需要。有兩種方法可以把它從Bean Factory中刪除掉。

1.如果Bean實(shí)現(xiàn)了DisposableBean接口,destory()方法被調(diào)用。

2.如果指定了訂制的銷(xiāo)毀方法,就調(diào)用這個(gè)方法。

  Bean在Spring應(yīng)用上下文的生命周期與在Bean工廠(chǎng)中的生命周期只有一點(diǎn)不同,唯一不同的是,如果Bean實(shí)現(xiàn)了ApplicationContextAwre接口,setApplicationContext()方法被調(diào)用。


MySQL Hash索引和B-Tree索引的區(qū)別?

  MySQL Hash索引結(jié)構(gòu)的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree 索引需要從根節(jié)點(diǎn)到枝節(jié)點(diǎn),最后才能訪(fǎng)問(wèn)到頁(yè)節(jié)點(diǎn)這樣多次的IO訪(fǎng)問(wèn),所以 Hash 索引的查詢(xún)效率要遠(yuǎn)高于 B-Tree 索引。
  可能很多人又有疑問(wèn)了,既然 Hash 索引的效率要比 B-Tree 高很多,為什么大家不都用 Hash 索引而還要使用 B-Tree 索引呢?任何事物都是有兩面性的,Hash 索引也一樣,雖然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也帶來(lái)了很多限制和弊端,主要有以下這些。
(1)MySQL Hash索引僅僅能滿(mǎn)足"=","IN"和"< >"查詢(xún),不能使用范圍查詢(xún)。
由于 MySQL Hash索引比較的是進(jìn)行 Hash 運(yùn)算之后的 Hash 值,所以它只能用于等值的過(guò)濾,不能用于基于范圍的過(guò)濾,因?yàn)榻?jīng)過(guò)相應(yīng)的 Hash 算法處理之后的 Hash 值的大小關(guān)系,并不能保證和Hash運(yùn)算前完全一樣。
(2)MySQL Hash索引無(wú)法被用來(lái)避免數(shù)據(jù)的排序操作。
由于 MySQL Hash索引中存放的是經(jīng)過(guò) Hash 計(jì)算之后的 Hash 值,而且Hash值的大小關(guān)系并不一定和 Hash 運(yùn)算前的鍵值完全一樣,所以數(shù)據(jù)庫(kù)無(wú)法利用索引的數(shù)據(jù)來(lái)避免任何排序運(yùn)算;
(3)MySQL Hash索引不能利用部分索引鍵查詢(xún)。
對(duì)于組合索引,Hash 索引在計(jì)算 Hash 值的時(shí)候是組合索引鍵合并后再一起計(jì)算 Hash 值,而不是多帶帶計(jì)算 Hash 值,所以通過(guò)組合索引的前面一個(gè)或幾個(gè)索引鍵進(jìn)行查詢(xún)的時(shí)候,Hash 索引也無(wú)法被利用。
(4)MySQL Hash索引在任何時(shí)候都不能避免表掃描。
前面已經(jīng)知道,Hash 索引是將索引鍵通過(guò) Hash 運(yùn)算之后,將 Hash運(yùn)算結(jié)果的 Hash 值和所對(duì)應(yīng)的行指針信息存放于一個(gè) Hash 表中,由于不同索引鍵存在相同 Hash 值,所以即使取滿(mǎn)足某個(gè) Hash 鍵值的數(shù)據(jù)的記錄條數(shù),也無(wú)法從 Hash 索引中直接完成查詢(xún),還是要通過(guò)訪(fǎng)問(wèn)表中的實(shí)際數(shù)據(jù)進(jìn)行相應(yīng)的比較,并得到相應(yīng)的結(jié)果。
(5)MySQL Hash索引遇到大量Hash值相等的情況后性能并不一定就會(huì)比B-Tree索引高。
對(duì)于選擇性比較低的索引鍵,如果創(chuàng)建 Hash 索引,那么將會(huì)存在大量記錄指針信息存于同一個(gè) Hash 值相關(guān)聯(lián)。這樣要定位某一條記錄時(shí)就會(huì)非常麻煩,會(huì)浪費(fèi)多次表數(shù)據(jù)的訪(fǎng)問(wèn),而造成整體性能低下。


單例與靜態(tài)變量的區(qū)別

單例的特點(diǎn):

1、保證某類(lèi)只存在唯一實(shí)例。
2、該類(lèi)本身完成自身的初始化。
3、獲取該唯一實(shí)例的方式非常明確,可以通過(guò)該類(lèi)本身定義的靜態(tài)方法getInstance()獲取該類(lèi)的唯一實(shí)例引用。

靜態(tài)變量定義某類(lèi)的實(shí)例引用特點(diǎn)
1、該類(lèi)的實(shí)例引用的靜態(tài)變量可定義在任何文檔類(lèi)當(dāng)中。
2、獲取該類(lèi)的實(shí)例引用的靜態(tài)變量,可以通過(guò)定義該靜態(tài)變量的類(lèi)名通過(guò)點(diǎn)語(yǔ)法進(jìn)行訪(fǎng)問(wèn)該引用。
3、任何位置可以對(duì)該靜態(tài)變量進(jìn)行重新賦值。

  通過(guò)這兩者方式的特點(diǎn),我們可以很明顯的看出兩者之間的區(qū)別。(這一切都是基于某類(lèi)只需要存在一個(gè)實(shí)例對(duì)象的前提來(lái)討論)
首先靜態(tài)變量方式不能確保某類(lèi)的實(shí)例的唯一性,這樣在項(xiàng)目中,可能因?yàn)樵谀硞€(gè)文檔類(lèi)中對(duì)該靜態(tài)變量進(jìn)行再次賦值,存不可意料的風(fēng)險(xiǎn)(這種風(fēng)險(xiǎn)可以規(guī)避)。同樣的,因?yàn)殪o態(tài)變量的定義的位置不確定,所以需要協(xié)議商定,這些靜態(tài)變量分類(lèi)別進(jìn)行定義在一個(gè)固定的位置(比如說(shuō)某個(gè)專(zhuān)門(mén)存放靜態(tài)變量方式的某類(lèi)的對(duì)象的引用的文檔類(lèi)當(dāng)中)。
  而單例模式也就是靜態(tài)變量方式創(chuàng)建一個(gè)類(lèi)的實(shí)例引用所帶來(lái)的缺陷的改善。首先解決引用的唯一實(shí)例可能被重新賦值的問(wèn)題,單例模式中的getInstance()靜態(tài)方法實(shí)現(xiàn)時(shí),采用懶漢式創(chuàng)建一個(gè)對(duì)象(當(dāng)然這只是創(chuàng)建方式的一種),規(guī)避了這一風(fēng)險(xiǎn),無(wú)則創(chuàng)建,有則跳過(guò)創(chuàng)建。其次,getInstance()靜態(tài)方法定義在該類(lèi)的內(nèi)部,獲取該類(lèi)對(duì)象的引用位置非常明確,無(wú)需額外的溝通商定,團(tuán)隊(duì)成員拿起即用。最后一個(gè)區(qū)別并不是很明顯,聲明一個(gè)靜態(tài)變量,實(shí)際上,我們會(huì)直接對(duì)其進(jìn)行初始化賦值,這樣,在內(nèi)存占用上,所占用的內(nèi)存為該初始化賦值對(duì)象實(shí)際的內(nèi)存。而單例模式可以通過(guò)懶漢創(chuàng)建法延遲該內(nèi)存的占用,要知道,當(dāng)一個(gè)靜態(tài)變量只進(jìn)行聲明,而不進(jìn)行初始化時(shí),實(shí)際的內(nèi)存占用只有4個(gè)字節(jié)(筆者個(gè)人推測(cè),這四個(gè)字節(jié)只是一個(gè)指針地址所占用的內(nèi)存空間)。


關(guān)于HashMap與HashTable

HashMap/HashTable初始容量大小和每次擴(kuò)充容量大小的不同

可以看到HashTable默認(rèn)的初始大小為11,之后每次擴(kuò)充為原來(lái)的2n+1。HashMap默認(rèn)的初始化大小為16,之后每次擴(kuò)充為原來(lái)的2倍。還有我沒(méi)列出代碼的一點(diǎn),就是如果在創(chuàng)建時(shí)給定了初始化大小,那么HashTable會(huì)直接使用你給定的大小,而HashMap會(huì)將其擴(kuò)充為2的冪次方大小。

也就是說(shuō)HashTable會(huì)盡量使用素?cái)?shù)、奇數(shù)。而HashMap則總是使用2的冪作為哈希表的大小。我們知道當(dāng)哈希表的大小為素?cái)?shù)時(shí),簡(jiǎn)單的取模哈希的結(jié)果會(huì)更加均勻(具體證明,見(jiàn)這篇文章),所以單從這一點(diǎn)上看,HashTable的哈希表大小選擇,似乎更高明些。但另一方面我們又知道,在取模計(jì)算時(shí),如果模數(shù)是2的冪,那么我們可以直接使用位運(yùn)算來(lái)得到結(jié)果,效率要大大高于做除法。所以從hash計(jì)算的效率上,又是HashMap更勝一籌。

所以,事實(shí)就是HashMap為了加快hash的速度,將哈希表的大小固定為了2的冪。當(dāng)然這引入了哈希分布不均勻的問(wèn)題,所以HashMap為解決這問(wèn)題,又對(duì)hash算法做了一些改動(dòng)。具體我們來(lái)看看,在獲取了key對(duì)象的hashCode之后,HashTable和HashMap分別是怎樣將他們hash到確定的哈希桶(Entry數(shù)組位置)中的。

正如我們所言,HashMap由于使用了2的冪次方,所以在取模運(yùn)算時(shí)不需要做除法,只需要位的與運(yùn)算就可以了。但是由于引入的hash沖突加劇問(wèn)題,HashMap在調(diào)用了對(duì)象的hashCode方法之后,又做了一些位運(yùn)算在打散數(shù)據(jù)。關(guān)于這些位計(jì)算為什么可以打散數(shù)據(jù)的問(wèn)題,本文不再展開(kāi)了。感興趣的可以看這里。

HashMap是支持null鍵和null值的,而HashTable在遇到null時(shí),會(huì)拋出NullPointerException異常。

這并不是因?yàn)镠ashTable有什么特殊的實(shí)現(xiàn)層面的原因?qū)е虏荒苤С謓ull鍵和null值,這僅僅是因?yàn)镠ashMap在實(shí)現(xiàn)時(shí)對(duì)null做了特殊處理,將null的hashCode值定為了0,從而將其存放在哈希表的第0個(gè)bucket中。


JSP指令元素與動(dòng)作元素的區(qū)別

1:先將top.jsp中的java腳本和jsp指令都執(zhí)行完畢以后再將top.jsp頁(yè)面加入到引用頁(yè)面中。

2:<%@ include file="top.jsp"%>靜態(tài)讀?。簞t是將top.jsp的整個(gè)頁(yè)面不加解析(無(wú)論是腳本還是指令)統(tǒng)統(tǒng)讀入到引用頁(yè)面中,然后和引用頁(yè)面一起進(jìn)行解析(即開(kāi)始執(zhí)行腳本和指令)。

3:區(qū)別:其實(shí)上邊的兩條就是區(qū)別,但是需要注意的是用<%@ include file=""%>的時(shí)候被引用頁(yè)面中不能再出現(xiàn)其他網(wǎng)頁(yè)標(biāo)簽和page指令了,否則會(huì)沖突的

(jsp:include page="")

父頁(yè)面和包含進(jìn)來(lái)的頁(yè)面多帶帶編譯,多帶帶翻譯成servlet后,在前臺(tái)拼成一個(gè)HTML頁(yè)面。

(%@include file=""%)

父頁(yè)面和包含進(jìn)來(lái)的頁(yè)面,代碼合并后,才一起翻譯成servlet,反饋到前臺(tái),形成一個(gè)HTML頁(yè)面。

由此我們知道:jsp頁(yè)面是把include指令元素(<%@ include file=""%>)所指定的頁(yè)面的實(shí)際內(nèi)容(也就是代碼段)加入到引入它的jsp頁(yè)面中,合成一個(gè)文件后被jsp容器將它轉(zhuǎn)化成servlet??梢钥吹竭@時(shí)會(huì)產(chǎn)生一個(gè)臨時(shí)class文件和一個(gè)servlet源文件。而動(dòng)作元素()是在請(qǐng)求處理階段引入的,會(huì)被JSP容器生成兩個(gè)臨時(shí)class文件和兩個(gè)servlet原文件。而引入的只是servlet的輸出結(jié)果,即JspWriter對(duì)象的輸出結(jié)果,而不是jsp的源代碼。

java是在服務(wù)器端運(yùn)行的代碼,jsp在服務(wù)器的servlet里運(yùn)行,而javascript和html都是在瀏覽器端運(yùn)行的代碼。所以加載執(zhí)行順序是是java>jsp>js。

所有的JSP都會(huì)在客戶(hù)端發(fā)出請(qǐng)求后被容器轉(zhuǎn)譯成servlet的源代碼(java),然后再將源碼(java)編譯成servlet的類(lèi)(class),放入到內(nèi)存里面。


可重入鎖 公平鎖 讀寫(xiě)鎖

1.可重入鎖

如果鎖具備可重入性,則稱(chēng)作為可重入鎖。

像Synchronized和ReentrantLock都是可重入鎖,可重入性在我看來(lái)實(shí)際上表明了鎖的分配機(jī)制:

基于線(xiàn)程的分配,而不是基于方法調(diào)用的分配。

舉個(gè)簡(jiǎn)單的例子,當(dāng)一個(gè)線(xiàn)程執(zhí)行到某個(gè)Synchronized方法時(shí),比如說(shuō)method1,而在method1中會(huì)調(diào)用另外一個(gè)Synchronized方法method2,此時(shí)線(xiàn)程不必重新去申請(qǐng)鎖,而是可以直接執(zhí)行方法method2。

class MyClass {
    public synchronized void method1() {
        method2();
    }
     
    public synchronized void method2() {
         
    }
}

上述代碼中的兩個(gè)方法method1和method2都用Synchronized修飾了。

假如某一時(shí)刻,線(xiàn)程A執(zhí)行到了method1,此時(shí)線(xiàn)程A獲取了這個(gè)對(duì)象的鎖,而由于method2也是Synchronized方法,假如Synchronized不具備可重入性,此時(shí)線(xiàn)程A需要重新申請(qǐng)鎖。

但是這就會(huì)造成一個(gè)問(wèn)題,因?yàn)榫€(xiàn)程A已經(jīng)持有了該對(duì)象的鎖,而又在申請(qǐng)獲取該對(duì)象的鎖,這樣就會(huì)線(xiàn)程A一直等待永遠(yuǎn)不會(huì)獲取到的鎖。

而由于Synchronized和Lock都具備可重入性,所以不會(huì)發(fā)生上述現(xiàn)象。

2.可中斷鎖

可中斷鎖:顧名思義,就是可以響應(yīng)中斷的鎖。

在Java中,Synchronized就不是可中斷鎖,而Lock是可中斷鎖。

如果某一線(xiàn)程A正在執(zhí)行鎖中的代碼,另一線(xiàn)程B正在等待獲取該鎖,可能由于等待時(shí)間過(guò)長(zhǎng),線(xiàn)程B不想等待了,想先處理其他事情,我們可以讓它中斷自己或者在別的線(xiàn)程中中斷它,這種就是可中斷鎖。

在前面演示LockInterruptibly()的用法時(shí)已經(jīng)體現(xiàn)了Lock的可中斷性。

3.公平鎖

公平鎖即盡量以請(qǐng)求鎖的順序來(lái)獲取鎖。比如同是有多個(gè)線(xiàn)程在等待一個(gè)鎖,當(dāng)這個(gè)鎖被釋放時(shí),等待時(shí)間最久的線(xiàn)程(最先請(qǐng)求的線(xiàn)程)會(huì)獲得該所,這種就是公平鎖。

非公平鎖即無(wú)法保證鎖的獲取是按照請(qǐng)求鎖的順序進(jìn)行的。這樣就可能導(dǎo)致某個(gè)或者一些線(xiàn)程永遠(yuǎn)獲取不到鎖。

在Java中,Synchronized就是非公平鎖,它無(wú)法保證等待的線(xiàn)程獲取鎖的順序。

而對(duì)于ReentrantLock和ReentrantReadWriteLock,它默認(rèn)情況下是非公平鎖,但是可以設(shè)置為公平鎖。這一點(diǎn)由構(gòu)造函數(shù)可知:

public ReentrantLock() {
        sync = new NonfairSync();
    }


    public ReentrantLock(boolean fair) {
        sync = (fair)? new FairSync() : new NonfairSync();
    }

在ReentrantLock中定義了2個(gè)靜態(tài)內(nèi)部類(lèi),一個(gè)是NotFairSync,一個(gè)是FairSync,分別用來(lái)實(shí)現(xiàn)非公平鎖和公平鎖。

我們可以在創(chuàng)建ReentrantLock對(duì)象時(shí),通過(guò)知道布爾參數(shù)來(lái)決定使用非公平鎖還是公平鎖。

如果參數(shù)為true表示為公平鎖,為fasle為非公平鎖。默認(rèn)情況下,如果使用無(wú)參構(gòu)造器,則是非公平鎖。

另外在ReentrantLock類(lèi)中定義了很多方法,比如:

isFair() //判斷鎖是否是公平鎖
isLocked() //判斷鎖是否被任何線(xiàn)程獲取了
isHeldByCurrentThread() //判斷鎖是否被當(dāng)前線(xiàn)程獲取了
hasQueuedThreads() //判斷是否有線(xiàn)程在等待該鎖

在ReentrantReadWriteLock中也有類(lèi)似的方法,同樣也可以設(shè)置為公平鎖和非公平鎖。

不過(guò)要記住,ReentrantReadWriteLock并未實(shí)現(xiàn)Lock接口,它實(shí)現(xiàn)的是ReadWriteLock接口。

4.讀寫(xiě)鎖

讀寫(xiě)鎖將對(duì)一個(gè)資源(比如文件)的訪(fǎng)問(wèn)分成了2個(gè)鎖,一個(gè)讀鎖和一個(gè)寫(xiě)鎖。

正因?yàn)橛辛俗x寫(xiě)鎖,才使得多個(gè)線(xiàn)程之間的讀操作不會(huì)發(fā)生沖突。

ReadWriteLock就是讀寫(xiě)鎖,它是一個(gè)接口,ReentrantReadWriteLock實(shí)現(xiàn)了這個(gè)接口。

可以通過(guò)readLock()獲取讀鎖,通過(guò)writeLock()獲取寫(xiě)鎖。


數(shù)據(jù)庫(kù)的樂(lè)觀(guān)鎖與悲觀(guān)鎖

樂(lè)觀(guān)鎖是假定讀取的數(shù)據(jù),在寫(xiě)之前不會(huì)被更新。適用于數(shù)據(jù)更新不頻繁的場(chǎng)景。

相反,當(dāng)數(shù)據(jù)更新頻繁的時(shí)候,樂(lè)觀(guān)鎖的效率很低,因?yàn)榛旧厦看螌?xiě)的時(shí)候都要重復(fù)讀寫(xiě)兩次以上。

對(duì)于數(shù)據(jù)更新頻繁的場(chǎng)合,悲觀(guān)鎖效率更高 ;

對(duì)于數(shù)據(jù)更新不頻繁的場(chǎng)合,樂(lè)觀(guān)鎖效率更高;

一般來(lái)說(shuō)如果并發(fā)量很高的話(huà),建議使用悲觀(guān)鎖,否則的話(huà)就使用樂(lè)觀(guān)鎖。

如果并發(fā)量很高時(shí)使用樂(lè)觀(guān)鎖的話(huà),會(huì)導(dǎo)致很多的并發(fā)事務(wù)回滾、操作失敗。


工作內(nèi)存與主內(nèi)存

線(xiàn)程工作內(nèi)存是cpu寄存器和高速緩存的抽象描述,使用頻率高的數(shù)據(jù)從主存拷貝到高速緩存中,每個(gè)線(xiàn)程在cpu高速緩存中對(duì)拷貝的數(shù)據(jù)進(jìn)行讀取、計(jì)算、賦值,再在合適的時(shí)候同步更新到主存的該數(shù)據(jù),如i=1,i+1=2,若2在更新到主存前,其他線(xiàn)程是不知道該值被改變了,其他線(xiàn)程高速緩存中該值依然為1。

解決方法:需要各線(xiàn)程間可見(jiàn)的變量前加上volatile修飾,在一個(gè)線(xiàn)程的高速緩存中改變?cè)撝禃r(shí),其他線(xiàn)程會(huì)獲得該值的更新值。


垃圾回收器

垃圾收集器:

串行:Serial、Parallel、CMS

CMS:每個(gè)垃圾收集周期只有兩次短的停頓,開(kāi)始時(shí)有一個(gè)短的停頓,稱(chēng)為初始標(biāo)記;標(biāo)記從外部直接可達(dá)的老年代對(duì)象;然后在并發(fā)標(biāo)記階段,標(biāo)記所有從這些對(duì)象可達(dá)的存活對(duì)象;由于在標(biāo)記期間應(yīng)用可能正在運(yùn)行并更新引用,所以到并發(fā)標(biāo)記階段結(jié)束時(shí),未必所有存活的對(duì)象都能確保被標(biāo)記;所以必須再次停頓,稱(chēng)為重新標(biāo)記;最后一個(gè)階段是并發(fā)清除。


c3p0與dbcp區(qū)別

dbcp沒(méi)有自動(dòng)地去回收空閑連接的功能 c3p0有自動(dòng)回收空閑連接功能 。

兩者主要是對(duì)數(shù)據(jù)連接的處理方式不同!c3p0提供最大空閑時(shí)間,dbcp提供最大連接數(shù)。

前者當(dāng)連接超過(guò)最大空閑連接時(shí)間時(shí),當(dāng)前連接就會(huì)被斷掉。dbcp當(dāng)連接數(shù)超過(guò)最大連接數(shù)時(shí),所有連接都會(huì)被斷開(kāi)。

dbcp和c3p0都是單線(xiàn)程的,在高并發(fā)的環(huán)境下性能會(huì)非常低下;tomcat jdbc pool 近乎兼容 dbcp ,性能更高,異步方式獲取連接。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/40618.html

相關(guān)文章

  • Java學(xué)習(xí)路線(xiàn)總結(jié),搬磚工逆襲Java架構(gòu)師(全網(wǎng)最強(qiáng))

    摘要:哪吒社區(qū)技能樹(shù)打卡打卡貼函數(shù)式接口簡(jiǎn)介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號(hào)作者架構(gòu)師奮斗者掃描主頁(yè)左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無(wú)意間聽(tīng)到領(lǐng)導(dǎo)們的談話(huà),現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡(jiǎn)而言之,不缺干 ? 哪吒社區(qū)Java技能樹(shù)打卡?【打卡貼 day2...

    Scorpion 評(píng)論0 收藏0
  • Java識(shí)點(diǎn)總結(jié)Java容器-TreeSet)

    摘要:知識(shí)點(diǎn)總結(jié)容器知識(shí)點(diǎn)總結(jié)容器是接口的唯一實(shí)現(xiàn),可以確保集合元素處于排序狀態(tài),底層是一棵排序樹(shù)。底層使用紅黑樹(shù)算法進(jìn)行維護(hù),因此性能相對(duì)于來(lái)說(shuō)要差一些,因?yàn)閮?nèi)部會(huì)自動(dòng)進(jìn)行排序操作。 Java知識(shí)點(diǎn)總結(jié)(Java容器-TreeSet) @(Java知識(shí)點(diǎn)總結(jié))[Java, Java容器, JavaCollection, JavaSet] TreeSet TreeSet是SortedSet接...

    codergarden 評(píng)論0 收藏0
  • Java識(shí)點(diǎn)總結(jié)(JDBC-大文本對(duì)象的使用)

    摘要:知識(shí)點(diǎn)總結(jié)大文本對(duì)象的使用知識(shí)點(diǎn)總結(jié)用于存儲(chǔ)大量的文本數(shù)據(jù)大字段有些特殊,不同數(shù)據(jù)庫(kù)處理的方式不一樣,大字段的操作常常是以流的方式來(lái)處理。最大長(zhǎng)度為字符的列。 Java知識(shí)點(diǎn)總結(jié)(JDBC-大文本對(duì)象的使用) @(Java知識(shí)點(diǎn)總結(jié))[Java, JDBC] CLOB(Chaaracter Large Object) 用于存儲(chǔ)大量的文本數(shù)據(jù) 大字段有些特殊,不同數(shù)據(jù)庫(kù)處理的方式不一樣...

    aboutU 評(píng)論0 收藏0
  • Java識(shí)點(diǎn)總結(jié)(JDBC-二進(jìn)制對(duì)象的使用)

    摘要:知識(shí)點(diǎn)總結(jié)二進(jìn)制對(duì)象的使用知識(shí)點(diǎn)總結(jié)用于存儲(chǔ)大量的二進(jìn)制數(shù)據(jù)大字段有些特殊,不同數(shù)據(jù)庫(kù)處理的方式不一樣,大字段的操作常常是以流的方式來(lái)處理的。最大長(zhǎng)度為,字節(jié)的列。二進(jìn)制對(duì)象的使用插入一張圖片,并讀取出來(lái)存讀 Java知識(shí)點(diǎn)總結(jié)(JDBC-二進(jìn)制對(duì)象的使用) @(Java知識(shí)點(diǎn)總結(jié))[Java, JDBC] BLOB(Binary Large Object) 用于存儲(chǔ)大量的二進(jìn)制數(shù)據(jù)...

    Scholer 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<