JAVA编程思想学习手账初整理
redis:
緩存擊穿:對(duì)于訪問(wèn)過(guò)期的key查詢數(shù)據(jù)時(shí),加鎖,保證只有一個(gè)線程去底層獲取數(shù)據(jù),并返回結(jié)果緩存
緩存穿透:對(duì)于訪問(wèn)不存在的key時(shí)給出空結(jié)果并緩存,或引入布隆過(guò)濾器將數(shù)據(jù)提前緩存在布隆過(guò)濾器中
緩存雪崩:對(duì)于key采用隨機(jī)過(guò)期時(shí)間,避免大量的key在同一時(shí)間失效導(dǎo)致數(shù)據(jù)庫(kù)承載過(guò)高
持久化機(jī)制:
AOF:以追加 命令行記錄的方式記錄完整的日志? 優(yōu)點(diǎn):能夠完整恢復(fù)數(shù)據(jù)? 缺點(diǎn):恢復(fù)備份效率低
RDB:以二進(jìn)制的方式定時(shí)本分?jǐn)?shù)據(jù)? 優(yōu)點(diǎn):恢復(fù)備份效率高 缺點(diǎn):存在備份時(shí)間臨界區(qū)有丟失數(shù)據(jù)的可能
AOF + RDB:定時(shí)備份數(shù)據(jù)以二進(jìn)制的方式寫入文件,增量以命令行的記錄方式追加到文件當(dāng)中
數(shù)據(jù)類型:
string : 字符串(操作命令:set get append setrange getrange strlen)
? ? ? ? ? ? ?數(shù)值(操作命令:incr)? ?理解待加深
? ? ? ? ? ? ?bitmap?
list:? ? ? ?理解待加深
hash:? ?理解待加深
set:? ? ??理解待加深
sorted_set? ?理解待加深
?
并發(fā)編程:
synchronized (悲觀鎖,非公平鎖 ) 與 lock(reetrantLock,readwriteLock)(非公平鎖、樂(lè)觀鎖)
synchronized:1.6之前為重型鎖:線程獲取不到鎖會(huì)直接進(jìn)入(鎖池)隊(duì)列等待直到上一個(gè)線程釋放鎖之后才可以爭(zhēng)取鎖
? ? ? ? ? ? ? ? ? ? ? ? 1.6之后引入了鎖升級(jí)概念:JAVA對(duì)象頭部(MarkWord)包含鎖的信息,鎖升級(jí)狀態(tài)由無(wú)鎖到第一次加鎖升級(jí)為偏向鎖,第二次加鎖發(fā)生鎖競(jìng)爭(zhēng)則升級(jí)為輕量級(jí)鎖,輕量級(jí)鎖通過(guò)CAS自旋嘗試獲取鎖,如仍然獲取不到鎖則升級(jí)為重量級(jí)鎖進(jìn)入鎖池等待即1.6之前的方式
reetrantLock:底層采用CAS+AQS方式實(shí)現(xiàn)的鎖機(jī)制,當(dāng)一個(gè)線程想要獲取鎖先通過(guò)CAS自旋方式嘗試獲取鎖;如獲取不到則將當(dāng)前線程封裝為Node對(duì)象并存入AQS雙向隊(duì)列中,
? ? ? ? ? ? ? ? ? ? ? ? ? 1:AQS雙向隊(duì)列中已有線程在等待則將當(dāng)前線程掛接在已有線程后面并將指針互相連接上,且掛接成功后會(huì)將上一個(gè)Node節(jié)點(diǎn)的狀態(tài)(waitStatus)更新為-1表示上一個(gè)Node節(jié)點(diǎn)后面掛接的Node節(jié)點(diǎn)可被喚醒,處于AQS隊(duì)列的頭部Node節(jié)點(diǎn)會(huì)通過(guò)CAS方式嘗試獲取鎖資源
? ? ? ? ? ? ? ? ? ? ? ? ? 2:AQS雙向隊(duì)列中沒(méi)有線程在等待,則會(huì)創(chuàng)建一個(gè)虛擬的頭部節(jié)點(diǎn)(head)并將當(dāng)前Node節(jié)點(diǎn)掛接在虛擬節(jié)點(diǎn)之后,且將虛擬頭部節(jié)點(diǎn)(head)的狀態(tài)(waitStatus)設(shè)置為-1,以便更高效率的喚醒后面的線程節(jié)點(diǎn)
readwriteLock:讀讀不互斥,讀寫互斥,寫寫互斥;與reetranLock的區(qū)別在于更在細(xì)化的對(duì)鎖的顆粒度做了區(qū)別,以適用讀、寫的不同場(chǎng)景下的效率提升
concurrentHashMap:多線程并發(fā)的線程安全集合類;采用數(shù)組+單向鏈接+紅黑樹的數(shù)據(jù)結(jié)構(gòu)?,當(dāng)數(shù)組長(zhǎng)度大于64(實(shí)則為了優(yōu)化效率,數(shù)組的查詢時(shí)間復(fù)雜度為O(1))且單向鏈表長(zhǎng)度大于8(優(yōu)化效率,單向鏈接的查詢時(shí)間復(fù)雜度為O(n))時(shí)單向鏈接將轉(zhuǎn)化成紅黑樹結(jié)構(gòu)(時(shí)間復(fù)雜度Ologn)
CAS:比較并交換;程序運(yùn)行時(shí)會(huì)先從內(nèi)存中獲取數(shù)據(jù)到CPU進(jìn)行計(jì)算,再將計(jì)算完的結(jié)果寫入到內(nèi)存
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1:如果多個(gè)線程同一時(shí)間從內(nèi)存中獲取同一份的數(shù)據(jù)進(jìn)行計(jì)算則會(huì)引發(fā)數(shù)據(jù)不一致性的問(wèn)題(其他線程不能及時(shí)拿到某一線程計(jì)算完寫入的內(nèi)存中的數(shù)據(jù))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2:因此CAS的方式就是數(shù)據(jù)在CPU計(jì)算完之后寫入到內(nèi)存時(shí),會(huì)比較此時(shí)內(nèi)存中的值與當(dāng)前CPU中獲取的值是否一致,如一致則認(rèn)為沒(méi)有其它的線程修改過(guò)值正常寫入,反之就認(rèn)為值被其它線程篡改過(guò)則寫入失敗,再次通過(guò)CAS自旋方式直到寫入成功為止
?Executors創(chuàng)建線程池的幾種方式:
? newFixedThreadPool:固定線程數(shù)的線程池,當(dāng)添加的線程數(shù)超過(guò)定義的線程數(shù)時(shí)則進(jìn)入阻塞隊(duì)列(LinkedBlockingQueue),遵循FIFO(先進(jìn)先出)原則等待線程池中有空閑的線程數(shù)時(shí)再 進(jìn)行工作
? newScheduledThreadPool:固定線程數(shù)的定時(shí)任務(wù)線程池,底層采用延遲隊(duì)列(DelayedWorkQueue),可按固定的周期或者延遲多久的時(shí)間執(zhí)行任務(wù)
newCachedThreadPool:創(chuàng)建存活時(shí)間為60秒的線程池,當(dāng)前第一次有任務(wù)進(jìn)來(lái)會(huì)直接創(chuàng)建新線程,如60秒內(nèi)再次有任務(wù)進(jìn)入會(huì)復(fù)用已創(chuàng)建的存活線程執(zhí)行任務(wù),如60秒內(nèi)無(wú)任務(wù)進(jìn)入則會(huì)結(jié)束當(dāng)前線程池。如60秒外有任務(wù)進(jìn)入則會(huì)創(chuàng)建新的線程執(zhí)行;因?yàn)槿蝿?wù)只要提交線程池中,就必然會(huì)有線程處理
newSingleThreadExecutor:單例線程池,線程池中只有一個(gè)線程在工作,后續(xù)進(jìn)來(lái)的任務(wù)會(huì)進(jìn)入到阻塞對(duì)列中等待,遵循FIFO(先進(jìn)先出)原則,因此單例線程池適合按順序執(zhí)行的一系列任務(wù)
?newWorkStealingPool:并行計(jì)算底層使用ForkJoinPool;核心思想分而治之,線程竊取;使用場(chǎng)景,將一個(gè)大的任務(wù)按照一定的規(guī)則拆分(需手動(dòng)編寫拆分邏輯)?并放到當(dāng)前線程的阻塞隊(duì)列當(dāng)中,其它的空閑線程可以去處理有任務(wù)的線程的阻塞列隊(duì)中的任務(wù)?,優(yōu)點(diǎn):線程池中空閑線程可以被充分利用? ? ? ? ? ? ? ? ? ? ?
線程數(shù)計(jì)算:
核心線程數(shù)=cpu核數(shù) * cpu利用率 * (1 + w/c)=cpu核數(shù) * (1-阻塞系數(shù))
分布式
CAP:Consistency(一致性)? ?Availability(可用性)? ? Partition Tolerance(分區(qū)容錯(cuò)性)
微服務(wù)規(guī)定原則:CP?/??AP? ?三選二挑一?
C:保證微服務(wù)之間的數(shù)據(jù)強(qiáng)一致性,如zookeeper 發(fā)送消息必須等待其它節(jié)點(diǎn)都有反饋結(jié)果才可成功
A:保證微服務(wù)之間的可用,如某個(gè)節(jié)點(diǎn)掉線(需返回錯(cuò)誤響應(yīng)結(jié)果)但其他節(jié)點(diǎn)可正常使用則不影響整體的服務(wù)調(diào)用流程
P:保證由于網(wǎng)絡(luò)故障原因(網(wǎng)絡(luò)不可靠運(yùn)行)引起的服務(wù)波動(dòng)不影響整體的系統(tǒng)運(yùn)行,分布式系統(tǒng)的基石
nacos:阿里開源的微服務(wù)注冊(cè)中心
服務(wù)注冊(cè):微服務(wù)調(diào)用注冊(cè)中心客服端服務(wù)發(fā)送微服務(wù)實(shí)例信息完成注冊(cè)
服務(wù)心跳:客戶端會(huì)以默認(rèn)5秒的頻率向服務(wù)端發(fā)送心跳,告知注冊(cè)中心當(dāng)前服務(wù)的健康狀態(tài)
服務(wù)健康檢查:服務(wù)端啟用定時(shí)任務(wù)默認(rèn)每15秒檢查一次注冊(cè)服務(wù)列表的健康狀態(tài)如超過(guò)25秒未響應(yīng)則將服務(wù)置不健康狀態(tài)并下線
服務(wù)發(fā)現(xiàn):注冊(cè)中心的服務(wù)能被其它服務(wù)檢測(cè)到且可調(diào)用
服務(wù)同步:CP
Mysql
b+tree:矮胖形的樹狀結(jié)構(gòu);
? ? ? ? ? ? ? 1:非子葉節(jié)點(diǎn)存儲(chǔ)子葉節(jié)點(diǎn)的分區(qū)指針信息不存儲(chǔ)數(shù)據(jù)
? ? ? ? ? ? ? 2:子葉節(jié)點(diǎn)存儲(chǔ)主鍵信息(如有主鍵存儲(chǔ)主鍵列信息,否則存儲(chǔ)唯一索引列信息,兩者都未生成則會(huì)存儲(chǔ)生成隱式的rowid)
? 聯(lián)合索引:多列組合創(chuàng)建的索引;
? ? ? ? ? ? ? ?1:最左前綴原則:where 條件中必須包第一列的字段才會(huì)生效且需正確命中索引? ?
? ? ? ? ? ? ? ?2:原理:多列聯(lián)合索引先按第一列構(gòu)建b+tree結(jié)構(gòu),第二列基于第一列再構(gòu)建b+tree索引以此類推,因此第一列未命中索引,第二例自然不會(huì)命中索引
? ? ? ? ? ? ? ?3:回表查詢:對(duì)于普通索引(二級(jí)索引,非聚簇索引),構(gòu)建b+tree不會(huì)存儲(chǔ)該列數(shù)據(jù),而是存儲(chǔ)主鍵對(duì)應(yīng)的指針引用,所以普通索引查詢時(shí)先從主鍵索引中找到對(duì)應(yīng)的主鍵再根據(jù)主鍵查詢返回完整數(shù)據(jù)? ? 待加深理解
?InnoDB行級(jí)鎖:只有當(dāng)檢索條件中包含索引才使用行鎖,否則使用表鎖
?ACID:Atomicity(原子性),Consistency(一致性),Isolation(隔離性),持久性(durability)
?原子性:事務(wù)具有不可分割的性,一個(gè)事務(wù)被視為不可分割最小單元,在事務(wù)中的操作要么全部成功,要么全部失敗。意思就是不能只執(zhí)行事務(wù)中的一部分。
一致性: 事務(wù)將數(shù)據(jù)由一種一致性的狀態(tài)轉(zhuǎn)換到另一種一致性的狀態(tài),保證了事務(wù)開始之前和結(jié)束后的數(shù)據(jù)完整性
隔離性:一個(gè)事務(wù)的執(zhí)行不能被其它的干擾,即一個(gè)事務(wù)內(nèi)部中操作及使用的數(shù)據(jù)對(duì)其它事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾
持久性:一旦事務(wù)提交,事務(wù)中操作修改的數(shù)據(jù)會(huì)永久的保存到數(shù)據(jù)庫(kù)中,此時(shí)即使系統(tǒng)崩潰已提交的數(shù)據(jù)已不會(huì)丟失
?事務(wù)隔離級(jí)別:臟讀,幻讀,不可重復(fù)讀;理論上事務(wù)的隔離性可以保證事務(wù)之前的操作互不干擾,多個(gè)事務(wù)操作同一份數(shù)據(jù)必須等待上一個(gè)事務(wù)結(jié)束才可,這樣就成了串行,但效率極低。因此需要舍棄事務(wù)原本的隔離性,由此出現(xiàn)了事務(wù)隔離級(jí)別的概念
臟讀:一個(gè)事務(wù)讀到了另一個(gè)事務(wù)的已修改但未提交的數(shù)據(jù)
幻讀:一個(gè)事務(wù)執(zhí)行中,另一個(gè)事務(wù)將新紀(jì)錄添加到了正在讀取的事務(wù)中
不可重復(fù)度:當(dāng)事務(wù)內(nèi)相同的記錄被檢索兩次,且兩次的檢索結(jié)果不一樣
? ? ? ? ? ? ? ? ? ??
JVM
內(nèi)存結(jié)構(gòu)(運(yùn)行時(shí)數(shù)據(jù)區(qū)):堆(Heap),方法區(qū)(Method area),棧(本地方法棧(Native Method Stacks),虛擬機(jī)方法棧(Java? Virtual Machine Stacks)),程序計(jì)數(shù)器(The pc Register)
堆:java虛擬機(jī)所管理的內(nèi)存中最大的一塊;在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,被所有線程共享,java對(duì)象實(shí)例及數(shù)組都在堆上分配
方法區(qū):Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分,別名Non-Heap,目的是與java堆區(qū)分開來(lái),在java虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,被所有線程共享;用于存儲(chǔ)已被虛擬機(jī)加載的類信息,常量,靜態(tài)變量,即時(shí)編譯后的代碼等數(shù)據(jù);當(dāng)方法區(qū)無(wú)法滿足內(nèi)存要求時(shí)拋出OutOfMemoryError異常
虛擬機(jī)棧:是一個(gè)線程執(zhí)行的區(qū)域,保存著一個(gè)線程中方法的調(diào)用狀態(tài);
? ? ? ? ? ? ? 1:一個(gè)JAVA線程的運(yùn)行狀態(tài)由一個(gè)虛擬機(jī)棧保存,所以虛擬機(jī)棧是線程私有的,隨著線程的創(chuàng)建而創(chuàng)建
? ? ? ? ? ? ? 2:每一個(gè)被線程執(zhí)行的方法為該棧中的棧幀,即每個(gè)方法對(duì)應(yīng)一個(gè)棧幀;調(diào)用一個(gè)方法就會(huì)向棧中壓入一個(gè)棧幀,一個(gè)方法調(diào)用完成,就會(huì)把該棧幀從棧中彈出(FILO先壓入的棧幀后彈出)
程序計(jì)數(shù)器:線程的執(zhí)行權(quán)由CPU時(shí)間分片輪換調(diào)度,當(dāng)一個(gè)線程執(zhí)行過(guò)程中失去了執(zhí)行權(quán)時(shí)由程序計(jì)數(shù)器記錄當(dāng)前線程執(zhí)行的位置,待線程再次獲得執(zhí)行權(quán)時(shí)由程序計(jì)數(shù)器記錄的位置處開始執(zhí)行
? ? ? ? ? ? ? ?1:如果線程正在執(zhí)行的是JAVA方法,則計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址
? ? ? ? ? ? ? ?2:如果線程正在執(zhí)行的是native方法,則這個(gè)計(jì)數(shù)器為空
本地方法棧:如果線程執(zhí)行的是native方法,這些方法就會(huì)在本地方法棧中執(zhí)行;如果在JAVA方法中調(diào)用native方法,則以動(dòng)態(tài)鏈接的方式執(zhí)行調(diào)用
內(nèi)存結(jié)構(gòu)(概念):老年代(old),新生代(Eden,survive0,survice1)
垃圾回收(GC):
? ? Eden:1:在JAVA對(duì)象的頭部(markWord)中會(huì)存儲(chǔ)當(dāng)前的對(duì)象GC次數(shù),當(dāng)一個(gè)對(duì)象GC次數(shù)大于18時(shí)會(huì)將此對(duì)象從新生代轉(zhuǎn)移到老年代
? ? ? ? ? ? ? ? 2:當(dāng)有較大的對(duì)象進(jìn)入Eden區(qū)時(shí),首先會(huì)將Eden存在的不連續(xù)空間的對(duì)象轉(zhuǎn)移到survive0區(qū);當(dāng)survive0區(qū)中的對(duì)象總內(nèi)存超過(guò)survive0區(qū)的一半時(shí),將survive0區(qū)中對(duì)象復(fù)制到survive1區(qū)中以便在survive0區(qū)中空出連續(xù)的完整空間
? ? ? ? ? ??? ? 3:當(dāng)占有超過(guò)Eden區(qū)內(nèi)存一半的對(duì)象時(shí),會(huì)直接存放到老年代
? 什么時(shí)候會(huì)進(jìn)行垃圾回收:
? ? ? ? ? ? ? ? ?1:當(dāng)Eden區(qū)或S區(qū)內(nèi)存不夠用了
? ? ? ? ? ? ? ? ?2:老年代空間不夠用了
? ? ? ? ? ? ? ? ?3:方法區(qū)空間不夠用了
? ? ? ? ? ? ? ? 4:System.gc()
垃圾回收算法:標(biāo)記-清除,標(biāo)記復(fù)制
? ?可達(dá)性分析算法:通過(guò)GC Root對(duì)象(能作為GC Root:類加載器,Thread,虛擬機(jī)棧的本地變量表,static成員,常量引用,本地方法棧的變量等)開始向下尋找,看某個(gè)對(duì)象是否可達(dá),不可達(dá)的對(duì)象標(biāo)記回收
標(biāo)記-清除(Mark? Sweep)
? ? 標(biāo)記:找出內(nèi)存中需要回收的對(duì)象,并且把它們標(biāo)記出來(lái)。此時(shí)堆中的所有對(duì)象都要被掃描一遍,才能確定需要被回收的對(duì)象,比較耗時(shí)。
? ? 清除: 清除掉被標(biāo)記需要回收的對(duì)象,釋放出對(duì)應(yīng)的內(nèi)存空間。
? ? 缺點(diǎn):? 標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過(guò)程中需要分配較大對(duì)象時(shí),無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。
標(biāo)記-復(fù)制(Mark Copying)
? ? ? 將內(nèi)存劃分為兩塊相等的區(qū)域,每次只使用其中一塊,當(dāng)其中一塊使用完了,就將還存活的對(duì)象復(fù)制到另外一塊內(nèi)存上,然后把已使用過(guò)的內(nèi)存空間一次清除掉。
? ? ?缺點(diǎn):空間利用率降低
標(biāo)記-整理(Mark Compact)
? ? ?標(biāo)記過(guò)程與“標(biāo)記清除算法”一致,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓存活對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。 相較于“標(biāo)記復(fù)制算法”來(lái)說(shuō)少了一個(gè)“保留區(qū)”。
?Young區(qū):復(fù)制算法(對(duì)象在被分配之后,可能生命周期比較短,Young區(qū)復(fù)制率較高)
?Old區(qū):標(biāo)記清除或整理(Old區(qū)對(duì)象存活時(shí)間比較長(zhǎng),復(fù)制來(lái)復(fù)制去沒(méi)有必要,不如做個(gè)標(biāo)記再整理)
?垃圾收集器分類:
? ? ? ? 串行收集器:Serial、Serial Old
? ? ? ? 只能有一個(gè)垃圾回收線程執(zhí)行,用戶線程暫停;適用于內(nèi)存比較小的嵌入式設(shè)備
? ? ? ? 并行收集器(吞吐量?jī)?yōu)先):Parallel Scanvenge、 Parallel Old
? ? ? ? ?多條垃圾回收線程并行工作,但此時(shí)用戶線程仍然處理等待狀態(tài);適用于科學(xué)計(jì)算,后臺(tái)處理等交互場(chǎng)景
? ? ? ? 并發(fā)收集器(停頓時(shí)間優(yōu)先):CMS、G!
? ? ? ? 用戶線程和垃圾收集線程同時(shí)執(zhí)行(可能是交替執(zhí)行),垃圾收集線程在執(zhí)行的時(shí)候不會(huì)停頓用戶線程的運(yùn)行;適用于相對(duì)時(shí)間有要求的場(chǎng)景,比如Web
JVM查看參數(shù)
java -XX:+PrintFlagsFinal -version > flags.txt
常用參數(shù)含義
?
總結(jié)
以上是生活随笔為你收集整理的JAVA编程思想学习手账初整理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 电商零售业怎么做数据分析?这10篇作品看
- 下一篇: 阿里云短信验证码签名模板创建方法