java-八股文


一趾代、Java 基礎(chǔ)知識

1唠叛、Object 類相關(guān)方法

getClass

獲取當(dāng)前運行時對象的 Class 對象臀晃。

hashCode

返回對象的 hash 碼野瘦。

clone

拷貝當(dāng)前對象, 必須實現(xiàn) Cloneable 接口切心。淺拷貝對基本類型進行值拷貝朽寞,對引用類型拷貝引用挂洛;深拷貝對基本類型進行值拷貝黎比,對引用類型對象不但拷貝對象的引用還拷貝對象的相關(guān)屬性和方法超营。兩者不同在于深拷貝創(chuàng)建了一個新的對象。

equals

通過內(nèi)存地址比較兩個對象是否相等阅虫,String 類重寫了這個方法使用值來比較是否相等演闭。

toString

返回類名@哈希碼的 16 進制。

notify

喚醒當(dāng)前對象監(jiān)視器的任一個線程颓帝。

notifyAll

喚醒當(dāng)前對象監(jiān)視器上的所有線程米碰。

wait

1、暫停線程的執(zhí)行躲履;2、三個不同參數(shù)方法(等待多少毫秒聊闯;額外等待多少毫秒工猜;一直等待)3、與Thread.sleep(long time)相比菱蔬,sleep 使當(dāng)前線程休眠一段時間篷帅,并沒有釋放該對象的鎖史侣,wait 釋放了鎖。

finalize

對象被垃圾回收器回收時執(zhí)行的方法魏身。

2惊橱、基本數(shù)據(jù)類型

整型:byte(8)、short(16)箭昵、int(32)税朴、long(64)

浮點型:float(32)、double(64)

布爾型:boolean(8)

字符型:char(16)

3家制、序列化

Java 對象實現(xiàn)序列化要實現(xiàn) Serializable 接口正林。

反序列化并不會調(diào)用構(gòu)造方法。反序列的對象是由 JVM 自己生成的對象颤殴,不通過構(gòu)造方法生成觅廓。

序列化對象的引用類型成員變量,也必須是可序列化的涵但,否則杈绸,會報錯。

如果想讓某個變量不被序列化矮瘟,使用 transient 修飾瞳脓。

單例類序列化,需要重寫 readResolve() 方法芥永。

4篡殷、String、StringBuffer埋涧、StringBuilder

String

由 char[] 數(shù)組構(gòu)成板辽,使用了 final 修飾,是不可變對象棘催,可以理解為常量劲弦,線程安全;對 String 進行改變時每次都會新生成一個 String 對象醇坝,然后把指針指向新的引用對象邑跪。

StringBuffer 線程安全;StringBuiler 線程不安全呼猪。

操作少量字符數(shù)據(jù)用 String画畅;單線程操作大量數(shù)據(jù)用 StringBuilder;多線程操作大量數(shù)據(jù)用 StringBuffer宋距。

5轴踱、重載與重寫

重載

發(fā)生在同一個類中,方法名相同谚赎,參數(shù)的類型淫僻、個數(shù)诱篷、順序不同,方法的返回值和修飾符可以不同雳灵。

重寫

發(fā)生在父子類中棕所,方法名和參數(shù)相同,返回值范圍小于等于父類悯辙,拋出的異常范圍小于等于父類琳省,訪問修飾符范圍大于等于父類;如果父類方法訪問修飾符為 private 或者 final 則子類就不能重寫該方法笑撞。

6岛啸、final

修飾基本類型變量,一經(jīng)出初始化后就不能夠?qū)ζ溥M行修改茴肥。

修飾引用類型變量坚踩,不能夠指向另一個引用。

修飾類或方法瓤狐,不能被繼承或重寫瞬铸。

7、反射

在運行時動態(tài)的獲取類的完整信息

增加程序的靈活性

JDK 動態(tài)代理使用了反射

8础锐、JDK 動態(tài)代理

使用步驟

創(chuàng)建接口及實現(xiàn)類

實現(xiàn)代理處理器:實現(xiàn) InvokationHandler 嗓节,實現(xiàn) invoke(Proxy proxy,Method method皆警,Object[] args) 方法

通過 Proxy.newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h) 獲得代理類

通過代理類調(diào)用方法拦宣。

9、Java IO

普通 IO 信姓,面向流鸵隧,同步阻塞線程。

NIO意推,面向緩沖區(qū)豆瘫,同步非阻塞。

二菊值、Java 集合框架

1外驱、List(線性結(jié)構(gòu))

ArrayList

Object[] 數(shù)組實現(xiàn),默認(rèn)大小為 10 腻窒,支持隨機訪問昵宇,連續(xù)內(nèi)存空間,插入末尾時間復(fù)雜度 o(1)儿子,插入第 i 個位置時間復(fù)雜度 o(n - i)瓦哎。擴容,大小變?yōu)?b>1.5倍,Arrays.copyOf(底層 System.ArrayCopy)杭煎,復(fù)制到新數(shù)組,指針指向新數(shù)組卒落。

Vector

類似 ArrayList羡铲,線程安全,擴容默認(rèn)增長為原來的2倍儡毕,還可以指定增長空間長度也切。

LinkedList

基于鏈表實現(xiàn),1.7 為雙向鏈表腰湾,1.6 為雙向循環(huán)鏈表雷恃,取消循環(huán)更能分清頭尾。

2费坊、Map(K倒槐,V 對)

HashMap

底層數(shù)據(jù)結(jié)構(gòu),JDK 1.8 是數(shù)組 + 鏈表 + 紅黑樹附井,JDK 1.7 無紅黑樹讨越。鏈表長度大于 8 時,轉(zhuǎn)化為紅黑樹永毅,優(yōu)化查詢效率把跨。

初始容量為16,通過 tableSizeFor 保證容量為 2 的冪次方沼死。尋址方式着逐,高位異或,(n-1)&h取模意蛀,優(yōu)化速度耸别。

擴容機制,當(dāng)元素數(shù)量大于容量 x 負(fù)載因子 0.75 時浸间,容量擴大為原來的 2 倍太雨,新建一個數(shù)組,然后轉(zhuǎn)移到新數(shù)組魁蒜。

基于 Map 實現(xiàn)囊扳。

線程不安全。

HashMap (1.7) 多線程循環(huán)鏈表問題

在多線程環(huán)境下兜看,進行擴容時锥咸,1.7 下的 HashMap 會形成循環(huán)鏈表。

怎么形成循環(huán)鏈表:

假設(shè)有一 HashMap 容量為 2 细移, 在數(shù)組下標(biāo) 1 位置以 A -> B 鏈表形式存儲搏予。有一線程對該 map 做 put 操作,由于觸發(fā)擴容條件弧轧,需要進行擴容雪侥。這時另一個線程也 put 操作碗殷,同樣需要擴容,并完成了擴容操作速缨,由于復(fù)制到新數(shù)組是頭部插入锌妻,所以 1 位置變?yōu)?B -> A 。這時第一個線程繼續(xù)做擴容操作旬牲,首先復(fù)制 A 仿粹,然后復(fù)制 B ,再判斷 B.next 是否為空時原茅,由于第二個線程做了擴容操作吭历,導(dǎo)致 B.next = A,所以在將 A 放到 B 前擂橘,A.next 又等于 B 晌区,導(dǎo)致循環(huán)鏈表出現(xiàn)。

HashTable

線程安全通贞,方法基本全用 Synchronized 修飾契讲。

初始容量為 11 ,擴容為 2n + 1 滑频。

繼承Dictionary類捡偏。

ConcurrentHashMap

線程安全的 HashMap。

1.7 采用分段鎖的形式加鎖峡迷;1.8 使用 Synchronized 和 CAS 實現(xiàn)同步银伟,若數(shù)組的 Node 為空,則通過 CAS 的方式設(shè)置值绘搞,不為空則加在鏈表的第一個節(jié)點彤避。獲取第一個元素是否為空使用 Unsafe 類提供的 getObjectVolatile 保證可見性。

對于讀操作夯辖,數(shù)組由 volatile 修飾琉预,同時數(shù)組的元素為 Node,Node 的 K 使用 final 修飾蒿褂,V 使用 volatile 修飾圆米,下一個節(jié)點也用 volatile 修飾,保證多線程的可見性啄栓。

LinkedHashMap

LinkedHashMap 繼承自 HashMap娄帖,所以它的底層仍然是基于拉鏈?zhǔn)缴⒘薪Y(jié)構(gòu)即由數(shù)組和鏈表或紅黑樹組成。另外昙楚,LinkedHashMap 在上面結(jié)構(gòu)的基礎(chǔ)上近速,增加了一條雙向鏈表,使得上面的結(jié)構(gòu)可以保持鍵值對的插入順序。

TreeMap

有序的 Map削葱,紅黑樹結(jié)構(gòu)奖亚,可以自定義比較器來進行排序。

Collections.synchronizedMap 如何實現(xiàn) Map 線程安全析砸?

基于 Synchronized 遂蛀,實際上就是鎖住了當(dāng)前傳入的 Map 對象。

3干厚、Set(唯一值)

HashSet

基于 HashMap 實現(xiàn),使用了 HashMap 的 K 作為元素存儲螃宙,V 為 new Object() 蛮瞄,在 add() 方法中如果兩個元素的 Hash 值相同,則通過 equals 方法比較是否相等谆扎。

LinkedHashSet

LinkedHashSet 繼承于 HashSet挂捅,并且其內(nèi)部是通過 LinkedHashMap 來實現(xiàn)的。

TreeSet

紅黑樹實現(xiàn)有序唯一堂湖。

三闲先、Java 多線程

1、synchronized

修飾代碼塊

底層實現(xiàn)无蜂,通過 monitorenter & monitorexit 標(biāo)志代碼塊為同步代碼塊伺糠。

修飾方法

底層實現(xiàn),通過 ACC_SYNCHRONIZED 標(biāo)志方法是同步方法斥季。

修飾類 class 對象時训桶,實際鎖在類的實例上面。

單例模式

publicclassSingleton{privatestaticvolatileSingletoninstance=null;privateSingleton(){}publicstaticSingletongetInstance(){if(null==instance){synchronized(Singleton.class){if(null==instance){instance=newSingleton();}}}returninstance;}}

偏向鎖酣倾,自旋鎖舵揭,輕量級鎖,重量級鎖

通過 synchronized 加鎖躁锡,第一個線程獲取的鎖為偏向鎖午绳,這時有其他線程參與鎖競爭,升級為輕量級鎖映之,其他線程通過循環(huán)的方式嘗試獲得鎖拦焚,稱自旋鎖。若果自旋的次數(shù)達到一定的閾值杠输,則升級為重量級鎖耕漱。

需要注意的是,在第二個線程獲取鎖時抬伺,會先判斷第一個線程是否仍然存活螟够,如果不存活,不會升級為輕量級鎖。

2妓笙、Lock

ReentrantLock

基于 AQS (AbstractQueuedSynchronizer)實現(xiàn)若河,主要有 state (資源) + FIFO (線程等待隊列) 組成。

公平鎖與非公平鎖:區(qū)別在于在獲取鎖時寞宫,公平鎖會判斷當(dāng)前隊列是否有正在等待的線程萧福,如果有則進行排隊。

使用 lock() 和 unLock() 方法來加鎖解鎖辈赋。

ReentrantReadWriteLock

同樣基于 AQS 實現(xiàn)鲫忍,內(nèi)部采用內(nèi)部類的形式實現(xiàn)了讀鎖(共享鎖)和寫鎖 (排它鎖)。

非公平鎖吞吐量高

在獲取鎖的階段來分析钥屈,當(dāng)某一線程要獲取鎖時悟民,非公平鎖可以直接嘗試獲取鎖,而不是判斷當(dāng)前隊列中是否有線程在等待篷就。一定情況下可以避免線程頻繁的上下文切換射亏,這樣,活躍的線程有可能獲得鎖竭业,而在隊列中的鎖還要進行喚醒才能繼續(xù)嘗試獲取鎖智润,而且線程的執(zhí)行順序一般來說不影響程序的運行。

3未辆、volatile

Java 內(nèi)存模型

image.png

在多線程環(huán)境下窟绷,保證變量的可見性。使用了 volatile 修飾變量后咐柜,在變量修改后會立即同步到主存中钾麸,每次用這個變量前會從主存刷新。

禁止 JVM 指令重排序炕桨。

單例模式雙重校驗鎖變量為什么使用 volatile 修飾饭尝?

禁止 JVM 指令重排序,new Object()分為三個步驟:申請內(nèi)存空間献宫,將內(nèi)存空間引用賦值給變量钥平,變量初始化。如果不禁止重排序姊途,有可能得到一個未經(jīng)初始化的變量涉瘾。

4、線程的五種狀態(tài)

1). New

一個新的線程被創(chuàng)建捷兰,還沒開始運行立叛。

2). Runnable

一個線程準(zhǔn)備就緒,隨時可以運行的時候就進入了 Runnable 狀態(tài)贡茅。

Runnable 狀態(tài)可以是實際正在運行的線程秘蛇,也可以是隨時可以運行的線程其做。

多線程環(huán)境下,每個線程都會被分配一個固定長度的 CPU 計算時間赁还,每個線程運行一會兒就會停止讓其他線程運行妖泄,這樣才能讓每個線程公平的運行。這些等待 CPU 和正在運行的線程就處于 Runnable 狀態(tài)艘策。

3). Blocked

例如一個線程在等待 I/O 資源蹈胡,或者它要訪問的被保護代碼已經(jīng)被其他線程鎖住了,那么它就在阻塞 Blocked 狀態(tài)朋蔫,這個線程所需的資源到位后就轉(zhuǎn)入 Runnable 狀態(tài)罚渐。

4). Waiting(無限期等待)

如果一個線程在等待其他線程的喚醒,那么它就處于 Waiting 狀態(tài)驯妄。以下方法會讓線程進入等待狀態(tài):

Object.wait()

Thread.join()

LockSupport.park()

5). Timed Waiting(有期限等待)

無需等待被其他線程顯示喚醒荷并,在一定時間后有系統(tǒng)自動喚醒。

以下方法會讓線程進入有限等待狀態(tài):

Thread.sleep(sleeptime)

Object.wait(timeout)

Thread.join(timeout)

LockSupport.parkNanos(timeout)

LockSupport.parkUntil(timeout)

6). Terminated

一個線程正常執(zhí)行完畢富玷,或者意外失敗,那么就結(jié)束了既穆。

5赎懦、 wait() 與 sleep()

調(diào)用后線程進入 waiting 狀態(tài)。

wait() 釋放鎖幻工,sleep() 沒有釋放鎖励两。

調(diào)用 wait() 后需要調(diào)用 notify() 或 notifyAll() 方法喚醒線程。

wait() 方法聲明在 Object 中囊颅,sleep() 方法聲明在 Thread 中当悔。

6、 yield()

調(diào)用后線程進入 runnable 狀態(tài)踢代。

讓出 CPU 時間片盲憎,之后有可能其他線程獲得執(zhí)行權(quán),也有可能這個線程繼續(xù)執(zhí)行胳挎。

7饼疙、 join()

在線程 B 中調(diào)用了線程 A 的 Join()方法,直到線程 A 執(zhí)行完畢后慕爬,才會繼續(xù)執(zhí)行線程 B窑眯。

可以保證線程的順序執(zhí)行。

join() 方法必須在 線程啟動后調(diào)用才有意義医窿。

使用 wait() 方法實現(xiàn)磅甩。

9、線程使用方式

繼承 Tread 類

實現(xiàn) Runnable 接口

實現(xiàn) Callable 接口:帶有返回值

10姥卢、Runnable 和 Callable 比較

方法簽名不同卷要,void Runnable.run(),V Callable.call() throws Exception

是否允許有返回值渣聚,Callable允許有返回值

是否允許拋出異常,Callable允許拋出異常却妨。

提交任務(wù)方式饵逐,Callable使用Future<T> submit(Callable<T> task)返回 Future 對象,調(diào)用其 get() 方法可以獲得返回值彪标,Runnable使用void execute(Runnable command)倍权。

11、hapens-before

如果一個操作 happens-before 另一個操作捞烟,那么第一個操作的執(zhí)行結(jié)果將對第二個操作可見薄声,而且第一個操作的執(zhí)行順序排在第二個操作之前。

12题画、ThreadLocal

場景

主要用途是為了保持線程自身對象和避免參數(shù)傳遞默辨,主要適用場景是按線程多實例(每個線程對應(yīng)一個實例)的對象的訪問,并且這個對象很多地方都要用到苍息。

原理

為每個線程創(chuàng)建變量副本缩幸,不同線程之間不可見,保證線程安全竞思。使用 ThreadLocalMap 存儲變量副本表谊,以 ThreadLocal 為 K,這樣一個線程可以擁有多個 ThreadLocal 對象盖喷。

實際

使用多數(shù)據(jù)源時爆办,需要根據(jù)數(shù)據(jù)源的名字切換數(shù)據(jù)源,假設(shè)一個線程設(shè)置了一個數(shù)據(jù)源课梳,這個時候就有可能有另一個線程去修改數(shù)據(jù)源距辆,可以使用 ThreadLocal 維護這個數(shù)據(jù)源名字,使每個線程持有數(shù)據(jù)源名字的副本暮刃,避免線程安全問題跨算。

8、線程池

1)椭懊、分類

FixThreadPool 固定數(shù)量的線程池漂彤,適用于對線程管理,高負(fù)載的系統(tǒng)

SingleThreadPool 只有一個線程的線程池灾搏,適用于保證任務(wù)順序執(zhí)行

CacheThreadPool 創(chuàng)建一個不限制線程數(shù)量的線程池挫望,適用于執(zhí)行短期異步任務(wù)的小程序,低負(fù)載系統(tǒng)

ScheduledThreadPool 定時任務(wù)使用的線程池狂窑,適用于定時任務(wù)

2)媳板、線程池的幾個重要參數(shù)

int corePoolSize, 核心線程數(shù)

int maximumPoolSize, 最大線程數(shù)

long keepAliveTime, TimeUnit unit, 超過 corePoolSize 的線程的存活時長,超過這個時間泉哈,多余的線程會被回收蛉幸。

BlockingQueue<Runnable> workQueue,? 任務(wù)的排隊隊列

ThreadFactory threadFactory,? 新線程的產(chǎn)生方式

RejectedExecutionHandler handler)? 拒絕策略

3)破讨、線程池線程工作過程

corePoolSize -> 任務(wù)隊列 -> maximumPoolSize -> 拒絕策略

核心線程在線程池中一直存活,當(dāng)有任務(wù)需要執(zhí)行時奕纫,直接使用核心線程執(zhí)行任務(wù)提陶。當(dāng)任務(wù)數(shù)量大于核心線程數(shù)時,加入等待隊列匹层。當(dāng)任務(wù)隊列數(shù)量達到隊列最大長度時隙笆,繼續(xù)創(chuàng)建線程,最多達到最大線程數(shù)升筏。當(dāng)設(shè)置回收時間時撑柔,核心線程以外的空閑線程會被回收。如果達到了最大線程數(shù)還不能夠滿足任務(wù)執(zhí)行需求您访,則根據(jù)拒絕策略做拒絕處理铅忿。

4)、線程池拒絕策略(默認(rèn)拋出異常)

|:---|:---|

| AbortPolicy |? 拋出 RejectedExecutionException |

| DiscardPolicy |? 什么也不做灵汪,直接忽略 |

| DiscardOldestPolicy |? 丟棄執(zhí)行隊列中最老的任務(wù)檀训,嘗試為當(dāng)前提交的任務(wù)騰出位置 |

| CallerRunsPolicy |? 直接由提交任務(wù)者執(zhí)行這個任務(wù) |

5)、如何根據(jù) CPU 核心數(shù)設(shè)計線程池線程數(shù)量

IO 密集型 2nCPU

計算密集型 nCPU+1

其中 n 為 CPU 核心數(shù)量享言,可通過Runtime.getRuntime().availableProcessors()獲得核心數(shù):峻凫。

為什么加 1:即使當(dāng)計算密集型的線程偶爾由于缺失故障或者其他原因而暫停時,這個額外的線程也能確保 CPU 的時鐘周期不會被浪費担锤。

四蔚晨、Java 虛擬機

1乍钻、Java 內(nèi)存結(jié)構(gòu)

image.png

由線程共享肛循,存放 new 出來的對象,是垃圾回收器的主要工作區(qū)域银择。

線程私有多糠,分為 Java 虛擬機棧和本地方法棧,存放局部變量表浩考、操作棧夹孔、動態(tài)鏈接、方法出口等信息析孽,方法的執(zhí)行對應(yīng)著入棧到出棧的過程搭伤。

方法區(qū)

線程共享,存放已被加載的類信息袜瞬、常量怜俐、靜態(tài)變量、即時編譯器編譯后的代碼等信息邓尤,JDK 1.8 中方法區(qū)被元空間取代拍鲤,使用直接內(nèi)存贴谎。

2、Java 類加載機制

image.png

加載

加載字節(jié)碼文件季稳。

鏈接

驗證

驗證字節(jié)碼文件的正確性擅这。

準(zhǔn)備

為靜態(tài)變量分配內(nèi)存。

解析

將符號引用(如類的全限定名)解析為直接引用(類在實際內(nèi)存中的地址)景鼠。

初始化

為靜態(tài)變量賦初值仲翎。

雙親委派模式

當(dāng)一個類需要加載時,判斷當(dāng)前類是否被加載過莲蜘。已經(jīng)被加載的類會直接返回谭确,否則才會嘗試加載。加載的時候票渠,首先會把該請求委派該父類加載器的loadClass()處理逐哈,因此所有的請求最終都應(yīng)該傳送到頂層的啟動類加載器BootstrapClassLoader中。當(dāng)父類加載器無法處理時问顷,才由自己來處理昂秃。當(dāng)父類加載器為 null 時,會使用啟動類加載器BootstrapClassLoader作為父類加載器杜窄。

3肠骆、垃圾回收算法

Mark-Sweep(標(biāo)記-清除)算法

標(biāo)記需要回收的對象,然后清除塞耕,會造成許多內(nèi)存碎片蚀腿。

Copying(復(fù)制)算法

將內(nèi)存分為兩塊,只使用一塊扫外,進行垃圾回收時莉钙,先將存活的對象復(fù)制到另一塊區(qū)域,然后清空之前的區(qū)域筛谚。

Mark-Compact(標(biāo)記-整理)算法(壓縮法)

與標(biāo)記清除算法類似磁玉,但是在標(biāo)記之后,將存活對象向一端移動驾讲,然后清除邊界外的垃圾對象蚊伞。

Generational Collection(分代收集)算法

分為年輕代和老年代,年輕代時比較活躍的對象吮铭,使用復(fù)制算法做垃圾回收时迫。老年代每次回收只回收少量對象,使用標(biāo)記整理法谓晌。

4悔捶、典型垃圾回收器

CMS

簡介

以獲取最短回收停頓時間為目標(biāo)的收集器谨读,它是一種并發(fā)收集器星持,采用的是 Mark-Sweep 算法。

場景

如果你的應(yīng)用需要更快的響應(yīng)烧董,不希望有長時間的停頓,同時你的 CPU 資源也比較豐富胧奔,就適合適用 CMS 收集器逊移。

垃圾回收步驟

初始標(biāo)記 (Stop the World 事件 CPU 停頓, 很短) 初始標(biāo)記僅標(biāo)記一下 GC Roots 能直接關(guān)聯(lián)到的對象龙填,速度很快胳泉;

并發(fā)標(biāo)記 (收集垃圾跟用戶線程一起執(zhí)行) 并發(fā)標(biāo)記過程就是進行 GC Roots 查找的過程;

重新標(biāo)記 (Stop the World 事件 CPU 停頓岩遗,比初始標(biāo)記稍微長扇商,遠比并發(fā)標(biāo)記短) 修正由于并發(fā)標(biāo)記時應(yīng)用運行產(chǎn)生變化的標(biāo)記。

并發(fā)清理宿礁,標(biāo)記清除算法案铺;

缺點

并發(fā)標(biāo)記時和應(yīng)用程序同時進行,占用一部分線程梆靖,所以吞吐量有所下降控汉。

并發(fā)清除時和應(yīng)用程序同時進行,這段時間產(chǎn)生的垃圾就要等下一次 GC 再清除返吻。

采用的標(biāo)記清除算法姑子,產(chǎn)生內(nèi)存碎片,如果要新建大對象测僵,會提前觸發(fā) Full GC 街佑。

G1

簡介

是一款面向服務(wù)端應(yīng)用的收集器,它能充分利用多 CPU捍靠、多核環(huán)境沐旨。因此它是一款并行與并發(fā)收集器,并且它能建立可預(yù)測的停頓時間模型剂公,即可以設(shè)置 STW 的時間希俩。

垃圾回收步驟

1吊宋、初始標(biāo)記(stop the world 事件 CPU 停頓只處理垃圾)纲辽;

2、并發(fā)標(biāo)記(與用戶線程并發(fā)執(zhí)行)璃搜;

3拖吼、最終標(biāo)記(stop the world 事件 ,CPU 停頓處理垃圾);

4这吻、篩選回收(stop the world 事件 根據(jù)用戶期望的 GC 停頓時間回收)

特點

并發(fā)與并行

充分利用多核 CPU 吊档,使用多核來縮短 STW 時間,部分需要停頓應(yīng)用線程的操作唾糯,仍然可以通過并發(fā)保證應(yīng)用程序的執(zhí)行怠硼。

分代回收

新生代鬼贱,幸存帶,老年代

空間整合

總體看是采用標(biāo)記整理算法回收香璃,每個 Region 大小相等这难,通過復(fù)制來回收。

可預(yù)測的停頓時間

使用 -XX:MaxGCPauseMillis=200 設(shè)置最長目標(biāo)暫停值葡秒。

在 Java 語言中姻乓,可作為 GC Roots 的對象包括 4 種情況:

a) 虛擬機棧中引用的對象(棧幀中的本地變量表);

b) 方法區(qū)中類靜態(tài)屬性引用的對象眯牧;

c) 方法區(qū)中常量引用的對象蹋岩;

d) 本地方法棧中 Native 方法引用的對象。

五学少、MySQL (Inno DB)

1剪个、聚簇索引與非聚簇索引

image.png

都使用 B+ 樹作為數(shù)據(jù)結(jié)構(gòu)

聚簇索引中數(shù)據(jù)存在主鍵索引的葉子結(jié)點中,得到 key 即得到 data 版确;非聚簇索引的數(shù)據(jù)存在單獨的空間禁偎。

聚簇索引中輔助索引的葉子結(jié)點存的是主鍵;非聚簇索引中葉子結(jié)點存的是數(shù)據(jù)的地址阀坏;

聚簇索引的優(yōu)勢是找到主鍵就找到數(shù)據(jù)如暖,只需一次磁盤 IO ;當(dāng) B+ 樹的結(jié)點發(fā)生變化時忌堂,地址也會發(fā)生變化盒至,這時非聚簇索引需要更新所有的地址,增加開銷士修。

2枷遂、為何使用 B 樹做索引而不是紅黑樹?

索引很大棋嘲,通常作為文件存儲在磁盤上面酒唉,每次檢索索引都需要把索引文件加載進內(nèi)存,所以磁盤 IO 的次數(shù)是衡量索引數(shù)據(jù)結(jié)構(gòu)好壞的重要指標(biāo)沸移。應(yīng)用程序在從磁盤讀取數(shù)據(jù)時痪伦,不只是讀取需要的數(shù)據(jù),還會連同其他數(shù)據(jù)以頁的形式做預(yù)讀來減少磁盤 IO 的次數(shù)雹锣。數(shù)據(jù)庫的設(shè)計者將每個節(jié)點的大小設(shè)置為一頁的大小网沾,同時每次新建節(jié)點時都重新申請一個頁,這樣檢索一個節(jié)點只需要一次 IO蕊爵,根據(jù)索引定位到數(shù)據(jù)只需要 h- 1(h 為 B 樹高度辉哥,根節(jié)點常駐內(nèi)存) 次 IO,而 d (度,可以理解為寬度)與 h 稱反比醋旦,即 d 越大恒水,高度就越小,所以樹越扁饲齐,磁盤 IO 次數(shù)越少寇窑,即漸進復(fù)雜度為 logdN ,這也是為什么不選擇紅黑樹做索引的原因箩张。前面可以得出結(jié)論甩骏,d 越大,索引的性能越好先慷。節(jié)點由 key 和 data 組成饮笛,頁的大小一定,key 和 data 越小论熙,d 越大福青。B + 樹去掉了節(jié)點內(nèi)的 data 域,所以有更大的 d , 性能更好脓诡。

3无午、最左前綴原則

在 MySQL 中,可以指定多個列為索引祝谚,即聯(lián)合索引宪迟。比如 index(name,age) 交惯,最左前綴原則是指查詢時精確匹配到從最左邊開始的一列或幾列(name次泽;name&age),就可以命中索引席爽。如果所有列都用到了意荤,順序不同,查詢引擎會自動優(yōu)化為匹配聯(lián)合索引的順序只锻,這樣是能夠命中索引的玖像。

4、什么情況下可以用到 B 樹索引

(1) 定義有主鍵的列一定要建立索引齐饮。因為主鍵可以加速定位到表中的某行

(2) 定義有外鍵的列一定要建立索引捐寥。外鍵列通常用于表與表之間的連接,在其上創(chuàng)建索引可以加快表間的連接

(3) 對于經(jīng)常查詢的數(shù)據(jù)列最好建立索引沈矿。

① 對于需要在指定范圍內(nèi)快速或頻繁查詢的數(shù)據(jù)列上真,因為索引已經(jīng)排序咬腋,其指定的范圍是連續(xù)的羹膳,查詢可以利用索引的排序,加快查詢的時間

② 經(jīng)常用在where子句中的數(shù)據(jù)列根竿,將索引建立在where子句的集合過程中陵像,對于需要加速或頻繁檢索的數(shù)據(jù)列就珠,可以讓這些經(jīng)常參與查詢的數(shù)據(jù)列按照索引的排序進行查詢,加快查詢的時間醒颖。

5妻怎、事務(wù)隔離級別

Read uncommitted

讀未提交,可能出現(xiàn)臟讀泞歉,不可重復(fù)讀逼侦,幻讀。

Read committed

讀提交腰耙,可能出現(xiàn)不可重復(fù)讀榛丢,幻讀。

Repeatable read

可重復(fù)讀挺庞,可能出現(xiàn)臟讀晰赞。

Serializable

可串行化,同一數(shù)據(jù)讀寫都加鎖选侨,避免臟讀掖鱼,性能不忍直視。

Inno DB 默認(rèn)隔離級別為可重復(fù)讀級別援制,分為快照度和當(dāng)前讀戏挡,并且通過行鎖和間隙鎖解決了幻讀問題。

6晨仑、MVCC (多版本并發(fā)控制)

實現(xiàn)細節(jié)

每行數(shù)據(jù)都存在一個版本增拥,每次數(shù)據(jù)更新時都更新該版本。

修改時 Copy 出當(dāng)前版本隨意修改寻歧,各個事務(wù)之間互不干擾掌栅。

保存時比較版本號,如果成功(commit)码泛,則覆蓋原記錄猾封;失敗則放棄 copy(rollback)。

Inno DB 實現(xiàn)

在 InnoDB 中為每行增加兩個隱藏的字段噪珊,分別是該行數(shù)據(jù)創(chuàng)建時的版本號刪除時的版本號晌缘,這里的版本號是系統(tǒng)版本號(可以簡單理解為事務(wù)的 ID),每開始一個新的事務(wù)痢站,系統(tǒng)版本號就自動遞增磷箕,作為事務(wù)的 ID 。通常這兩個版本號分別叫做創(chuàng)建時間和刪除時間阵难。

詳細參考:《 臟讀岳枷、幻讀和不可重復(fù)讀》

六、Spring 相關(guān)

1、Bean 的作用域

|:---|:---|

| 類別 | 說明 |

|singleton| 默認(rèn)在 Spring 容器中僅存在一個實例 |

|prototype| 每次調(diào)用 getBean() 都重新生成一個實例 |

|request| 為每個 HTTP 請求生成一個實例 |

|session| 同一個 HTTP session 使用一個實例空繁,不同 session 使用不同實例 |

2殿衰、Bean 生命周期

簡單來說四步:

實例化 Instantiation

屬性賦值 Populate

初始化 Initialization

銷毀 Destruction

在這四步的基礎(chǔ)上面,Spring 提供了一些拓展點:

Bean 自身的方法: 這個包括了 Bean 本身調(diào)用的方法和通過配置文件中 %3Cbean %3E 的 init-method 和 destroy-method 指定的方法

Bean 級生命周期接口方法: 這個包括了 BeanNameAware盛泡、BeanFactoryAware闷祥、InitializingBean 和 DiposableBean 這些接口的方法

容器級生命周期接口方法:這個包括了 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現(xiàn),一般稱它們的實現(xiàn)類為“后處理器”傲诵。

工廠后處理器接口方法: 這個包括了 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工廠后處理器接口的方法凯砍。工廠后處理器也是容器級的。在應(yīng)用上下文裝配配置文件之后立即調(diào)用拴竹。

3果覆、Spring AOP

實現(xiàn)方式兩種:

JDK 動態(tài)代理:帶有接口的對象,在運行期實現(xiàn)

CGlib 靜態(tài)代理:在編譯期實現(xiàn)殖熟。

4局待、Spring 事務(wù)傳播行為

默認(rèn)PROPAGATION_REQUIRED,如果存在一個事務(wù)菱属,則支持當(dāng)前事務(wù)钳榨。如果沒有事務(wù)則開啟一個新的事務(wù)。

image.png

5纽门、Spring IoC

image.png

6薛耻、Spring MVC 工作流程

七、計算機網(wǎng)絡(luò)

1赏陵、TCP/IP 五層模型

image.png

2饼齿、瀏覽器輸入地址后做了什么?

image.png

3蝙搔、三次握手與四次揮手

三次握手

image.png

四次揮手

image.png

4缕溉、TIME_WAIT 與 CLOSE_WAIT

image.png

5、TCP 滑動窗口

TCP 流量控制吃型,主要使用滑動窗口協(xié)議证鸥,滑動窗口是接受數(shù)據(jù)端使用的窗口大小,用來告訴發(fā)送端接收端的緩存大小勤晚,以此可以控制發(fā)送端發(fā)送數(shù)據(jù)的大小枉层,從而達到流量控制的目的。這個窗口大小就是我們一次傳輸幾個數(shù)據(jù)赐写。對所有數(shù)據(jù)幀按順序賦予編號鸟蜡,發(fā)送方在發(fā)送過程中始終保持著一個發(fā)送窗口,只有落在發(fā)送窗口內(nèi)的幀才允許被發(fā)送挺邀;同時接收方也維持著一個接收窗口揉忘,只有落在接收窗口內(nèi)的幀才允許接收跳座。

6、TCP 粘包和拆包

現(xiàn)象

image.png

產(chǎn)生原因

1癌淮、要發(fā)送的數(shù)據(jù)大于 TCP 發(fā)送緩沖區(qū)剩余空間大小躺坟,將會發(fā)生拆包沦补。

2乳蓄、待發(fā)送數(shù)據(jù)大于 MSS(最大報文長度),TCP 在傳輸前將進行拆包夕膀。

3虚倒、要發(fā)送的數(shù)據(jù)小于 TCP 發(fā)送緩沖區(qū)的大小,TCP 將多次寫入緩沖區(qū)的數(shù)據(jù)一次發(fā)送出去产舞,將會發(fā)生粘包魂奥。

4、接收數(shù)據(jù)端的應(yīng)用層沒有及時讀取接收緩沖區(qū)中的數(shù)據(jù)易猫,將發(fā)生粘包耻煤。

解決方式

1、發(fā)送端給每個數(shù)據(jù)包添加包首部准颓,首部中應(yīng)該至少包含數(shù)據(jù)包的長度哈蝇,這樣接收端在接收到數(shù)據(jù)后,通過讀取包首部的長度字段攘已,便知道每一個數(shù)據(jù)包的實際長度了炮赦。

2、發(fā)送端將每個數(shù)據(jù)包封裝為固定長度(不夠的可以通過補 0 填充)样勃,這樣接收端每次從接收緩沖區(qū)中讀取固定長度的數(shù)據(jù)就自然而然的把每個數(shù)據(jù)包拆分開來吠勘。

3、可以在數(shù)據(jù)包之間設(shè)置邊界峡眶,如添加特殊符號剧防,這樣,接收端通過這個邊界就可以將不同的數(shù)據(jù)包拆分開辫樱。

八诵姜、MQ 消息隊列

1、場景作用

削峰填谷搏熄,異步解耦棚唆。

2、如何保證消息不被重復(fù)消費呢心例?

這個問題可以換個思路宵凌,保證消息重復(fù)消費,其實是保證程序的冪等性止后。無論消息如何重復(fù)瞎惫,程序運行的結(jié)果是一致的溜腐。比如消費消息后做數(shù)據(jù)庫插入操作,為了防止消息重復(fù)消費瓜喇,可以在插入前先查詢一下有沒有對應(yīng)的數(shù)據(jù)挺益。

3、怎么保證從消息隊列里拿到的數(shù)據(jù)按順序執(zhí)行乘寒?

消費端在接收到消息后放入內(nèi)存隊列望众,然后對隊列中的消息進行有序消費。

4伞辛、如何解決消息隊列的延時以及過期失效問題烂翰?消息隊列滿了以后該怎么處理?有幾百萬消息持續(xù)積壓幾小時蚤氏,說說怎么解決甘耿?

消息過期失效問題,如果消息一段時間不消費竿滨,導(dǎo)致過期失效了佳恬,消息就丟失了,只能重新查出丟失的消息于游,重新發(fā)送毁葱。

再來說消息積壓的問題:(思路是快速消費掉積壓的消息)

首先排查消費端問題,恢復(fù)消費端正常消費速度曙砂。

然后著手處理隊列中的積壓消息头谜。

停掉現(xiàn)有的 consumer。

新建一個 topic 鸠澈,設(shè)置之前 10 倍的 partation柱告,之前 10 倍的隊列。

寫一個分發(fā)程序笑陈,將積壓的消息均勻的輪詢寫入這些隊列际度。

然后臨時用 10 倍的機器部署 consumer,每一批 consumer 消費 1 個臨時的隊列涵妥。

消費完畢后乖菱,恢復(fù)原有架構(gòu)。

消息隊列滿了:只能邊接收邊丟棄蓬网,然后重新補回丟失的消息窒所,再做消費。

4帆锋、如何保證消息的可靠性傳輸(如何處理消息丟失的問題)吵取?

kafka 為例:

消費者丟了數(shù)據(jù):

每次消息消費后,由自動提交 offset 改為手動提交 offset 锯厢。

kafka 丟了消息:

比較常見的一個場景皮官,就是 kafka 某個 broker 宕機脯倒,然后重新選舉 partition 的 leader 時。要是此時其他的 follower 剛好還有些數(shù)據(jù)沒有同步捺氢,結(jié)果此時 leader 掛了藻丢,然后大家選舉某個 follower 成為 leader 之后,不就少了一些數(shù)據(jù)摄乒。

給 topic 設(shè)置replication.factor參數(shù):這個值必須大于 1悠反,要求每個 partition 必須有至少兩個副本。

在 kafka 服務(wù)端設(shè)置min.insync.replicas參數(shù):這個值必須大于 1缺狠,這個是要求一個 leader 至少感知到有至少一個 follower 還跟自己保持聯(lián)系问慎,沒掉隊萍摊,這樣才能確保 leader 掛了還有一個 follower挤茄。

在 producer 端設(shè)置acks=all:這個是要求每條數(shù)據(jù),必須是寫入所有 replica 之后冰木,才能認(rèn)為是寫成功了穷劈。

在 producer 端設(shè)置retries=MAX(很大很大很大的一個值,無限次重試的意思):這個是要求一旦寫入失敗踊沸,就無限重試歇终,卡在這里。

生產(chǎn)者丟了消息:

如果按照上述的思路設(shè)置了 ack=all逼龟,一定不會丟评凝,要求是,你的 leader 接收到消息腺律,所有的 follower 都同步到了消息之后奕短,才認(rèn)為本次寫成功了。如果沒滿足這個條件匀钧,生產(chǎn)者會自動不斷的重試翎碑,重試無限次。

九之斯、Redis

1日杈、數(shù)據(jù)類型

String

常用命令: set,get,decr,incr,mget 等。

Hash

常用命令: hget,hset,hgetall 等

List

常用命令: lpush,rpush,lpop,rpop,lrange 等

可以通過 lrange 命令佑刷,就是從某個元素開始讀取多少個元素莉擒,可以基于 list 實現(xiàn)分頁查詢。

Set

常用命令: sadd,spop,smembers,sunion 等

Sort Set

常用命令: zadd,zrange,zrem,zcard 等

2瘫絮、Redis 如何實現(xiàn) key 的過期刪除涨冀?

定期刪除和惰性刪除的形式。

定期刪除

Redis 每隔一段時間從設(shè)置過期時間的 key 集合中檀何,隨機抽取一些 key 蝇裤,檢查是否過期廷支,如果已經(jīng)過期做刪除處理。

惰性刪除

Redis 在 key 被訪問的時候檢查 key 是否過期栓辜,如果過期則刪除恋拍。

3、Redis 的持久化機制

數(shù)據(jù)快照(RDB)+ 修改數(shù)據(jù)語句文件(AOF)

4藕甩、如何解決 Redis 緩存雪崩和緩存穿透施敢?

緩存雪崩

緩存同一時間大面積的失效,所以狭莱,后面的請求都會落到數(shù)據(jù)庫上僵娃,造成數(shù)據(jù)庫短時間內(nèi)承受大量請求而崩掉。

解決方式

事前:保證 Redis 集群的穩(wěn)定性腋妙,發(fā)現(xiàn)機器宕機盡快補上默怨,設(shè)置合適的內(nèi)存淘汰策略。

事中:本地緩存 + 限流降級骤素,避免大量請求落在數(shù)據(jù)庫上匙睹。

事后:利用 Redis 持久化機制盡快恢復(fù)緩存。

緩存穿透

一般是黑客故意去請求緩存中不存在的數(shù)據(jù)济竹,導(dǎo)致所有的請求都落到數(shù)據(jù)庫上痕檬,造成數(shù)據(jù)庫短時間內(nèi)承受大量請求而崩掉。

解決方式

將不存在的數(shù)據(jù)列舉到一個足夠大的 map 上送浊,這樣遭到攻擊時梦谜,直接攔截 map 中的請求,請求到數(shù)據(jù)庫上面袭景⊙渥或是把不存在的也做緩存,值為 null 浴讯,設(shè)置過期時間朵夏。

5、如何使用 Redis 實現(xiàn)消息隊列榆纽?

Redis 實現(xiàn)消息隊列依賴于 Redis 集群的穩(wěn)定性仰猖,通常不建議使用。

Redis 自帶發(fā)布訂閱功能奈籽,基于 publish 和 subscribe 命令饥侵。

使用 List 存儲消息,lpush衣屏,rpop 分別發(fā)送接收消息躏升。

十、Nginx

Nginx 是一款輕量級的 Web 服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器狼忱。 Nginx 主要提供反向代

理膨疏、負(fù)載均衡一睁、動靜分離(靜態(tài)資源服務(wù))等服務(wù)。

1佃却、正向代理和反向代理

正向代理

代理客戶端訪問服務(wù)器者吁。典型:VPN

反向代理

代替服務(wù)器接收客戶端請求,然后轉(zhuǎn)發(fā)給服務(wù)器饲帅,服務(wù)器接收請求并將處理的結(jié)果通過代理服務(wù)器轉(zhuǎn)發(fā)給客戶端复凳。

2、負(fù)載均衡

將請求分?jǐn)偟蕉嗯_機器上去灶泵,高并發(fā)育八,增加吞吐量。

負(fù)載均衡算法

權(quán)重輪詢

fair

ip_hash

url_hash

3赦邻、動靜分離

動靜分離是讓動態(tài)網(wǎng)站里的動態(tài)網(wǎng)頁根據(jù)一定規(guī)則把不變的資源和經(jīng)常變的資源區(qū)分開來髓棋,動靜資源做好了拆分以后,我們就可以根據(jù)靜態(tài)資源的特點將其做緩存操作深纲,這就是網(wǎng)站靜態(tài)化處理的核心思路仲锄。

4劲妙、Nginx 四個組成部分

Nginx 二進制可執(zhí)行文件:由各模塊源碼編譯出一個文件

Nginx.conf 配置文件:控制 Nginx 行為

acess.log 訪問日志: 記錄每一條 HTTP 請求信息

error.log 錯誤日志:定位問題

作者:AYSAML

鏈接:http://www.reibang.com/p/2d46c351e30d

來源:簡書

著作權(quán)歸作者所有湃鹊。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處镣奋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末币呵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子侨颈,更是在濱河造成了極大的恐慌余赢,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哈垢,死亡現(xiàn)場離奇詭異妻柒,居然都是意外死亡,警方通過查閱死者的電腦和手機耘分,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門举塔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人求泰,你說我怎么就攤上這事央渣。” “怎么了渴频?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵芽丹,是天一觀的道長。 經(jīng)常有香客問我卜朗,道長拔第,這世上最難降的妖魔是什么咕村? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮蚊俺,結(jié)果婚禮上培廓,老公的妹妹穿的比我還像新娘。我一直安慰自己春叫,他們只是感情好肩钠,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著暂殖,像睡著了一般价匠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呛每,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天踩窖,我揣著相機與錄音,去河邊找鬼晨横。 笑死洋腮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的手形。 我是一名探鬼主播啥供,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼库糠!你這毒婦竟也來了伙狐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤瞬欧,失蹤者是張志新(化名)和其女友劉穎贷屎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艘虎,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡唉侄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了野建。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片属划。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贬墩,靈堂內(nèi)的尸體忽然破棺而出榴嗅,到底是詐尸還是另有隱情,我是刑警寧澤陶舞,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布嗽测,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏唠粥。R本人自食惡果不足惜疏魏,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晤愧。 院中可真熱鬧大莫,春花似錦、人聲如沸官份。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舅巷。三九已至羔味,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钠右,已是汗流浹背赋元。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留飒房,地道東北人搁凸。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像狠毯,于是被迫代替她去往敵國和親护糖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 一垃你、Java 基礎(chǔ)知識 1椅文、Object 類相關(guān)方法 getClass獲取當(dāng)前運行時對象的 Class 對象。 h...
    AYSAML閱讀 10,779評論 2 21
  • 【020 標(biāo)記接口】 標(biāo)記接口沒有任何成員和方法,表明的是能夠具備某種功能漓帅,通常是在編譯器進行類型校驗锨亏。 ① Cl...
    小笨特閱讀 732評論 0 1
  • 目錄: 線程基礎(chǔ) 線程池 各種各樣的鎖 并發(fā)容器 原子類 Java 內(nèi)存模型 線程協(xié)作 AQS 框架 一、線程基礎(chǔ)...
    王英豪閱讀 459評論 0 2
  • 1忙干、闡述下對象的自動裝箱和拆箱 2 基本數(shù)據(jù)類型的自動裝箱(autoboxing)器予、拆箱(unboxing)是自...
    FDoubleman閱讀 220評論 0 0
  • 介紹一下Syncronized鎖。如果用這個關(guān)鍵字修飾一個靜態(tài)方法捐迫,鎖住了什么乾翔?如果修飾成員方法,鎖住了什么? 修...
    隔壁丨王大爺閱讀 551評論 0 0