1. Java面向?qū)ο?/h2>
(1). 封裝
? 核心思想就是“隱藏細(xì)節(jié)”、“數(shù)據(jù)安全”慰枕、”重用”搞挣、”不必關(guān)心具體的實(shí)現(xiàn)”:將對象不需要讓外界訪問的成員變量和方法私有化育谬,只提供符合開發(fā)者意愿的公有方法來訪問這些數(shù)據(jù)和邏輯演熟,保證了數(shù)據(jù)的安全和程序的穩(wěn)定。
? 使用 private
修飾符把成員變量設(shè)置為私有霸褒,防止外部程序直接隨意調(diào)用或修改成員變量伴找,然后對外提供 public
的 set
和 get
方法按照開發(fā)者的意愿(可以編寫一些業(yè)務(wù)邏輯代碼,雖然很少這樣做)設(shè)置和獲取成員變量的值废菱。
(2). 繼承
? 用來提高了程序的復(fù)用性技矮、擴(kuò)展性
? 在實(shí)際開發(fā)中,應(yīng)該是先有子類,然后從中抽象封裝出父類
? 使用extends關(guān)鍵字實(shí)現(xiàn)
? Java只允許單繼承
? 父類中public和protected修飾的成員變量和方法可以被子類集成,構(gòu)造方法不能被繼承,但可以在子類中使用super()調(diào)用.子類中可以降低提高級(jí)別而不能降低.
? state修飾的變量或者方法屬于類,不能被繼承,但是子類可以直接調(diào)用
1). 方法重寫
? 方法重寫針對于實(shí)例方法.
? 方法名和參數(shù)必須一致,訪問修飾可以提高.(如果有必要可以才上方添加@Override注解自動(dòng)檢查)
? 返回值可以不一樣,但是只能是子類.
? 拋出異常必須是父類該方法拋出異常的子集
? 對于類方法(static,靜態(tài)),在子類中重寫是進(jìn)行隱藏(與重載的區(qū)別是如果向上進(jìn)行轉(zhuǎn)型,那么執(zhí)行的還是父類的方法)
2). 類實(shí)例化的過程
- 類加載
- 讀取class文件,加載到內(nèi)存,如果有父類,也會(huì)加載父類(==加載和驗(yàn)證==)
- 分配空間(==準(zhǔn)備==,會(huì)賦初值為默認(rèn)值)
- 執(zhí)行父類,子類靜態(tài)代碼塊(==初始化==,在這一步之前進(jìn)行了==解析==過程,將符號(hào)引用轉(zhuǎn)化為直接引用)
- 分配堆內(nèi)存空間,所有值為默認(rèn)值
- 對對象屬性進(jìn)行默認(rèn)初始化(顯示賦值的)
- 調(diào)用構(gòu)造方法
- 先調(diào)用父類構(gòu)造方法初始化父類數(shù)據(jù)
- 顯示的執(zhí)行子類的構(gòu)造代碼塊(與靜態(tài)代碼塊的區(qū)別在于不加static)
- 執(zhí)行子類構(gòu)造方法中的代碼進(jìn)行初始化
- 將地址賦給引用(外層new關(guān)鍵字那里)
(3). 多態(tài)
? 同一個(gè)行為具有多個(gè)不同表現(xiàn)形式.
? ==同一個(gè)接口使用不同的實(shí)例對象而執(zhí)行不同的操作.==
? Java中有兩種引用類型:編譯時(shí)類型和運(yùn)行時(shí)類型.編譯時(shí)類型由引用決定,運(yùn)行時(shí)類型由實(shí)例對象的類型決定.
條件:
- 繼承
- 重寫
- 父類引用指向子類對象
? 在編譯時(shí)會(huì)先判斷父類中有沒有此方法,如果沒有,則編譯錯(cuò)誤.如果有,再去調(diào)用子類中的同名方法(要么繼承下去,要么被重寫,只有被重寫才能體現(xiàn)出多態(tài)性)
? 在JVM底層實(shí)現(xiàn)中,實(shí)際上是由于方法的編譯期靜態(tài)多分派和運(yùn)行期動(dòng)態(tài)單分派來完成的.靜態(tài)多分派是指在編譯階段,會(huì)對方法的重載進(jìn)行選擇,這里是根據(jù)靜態(tài)類型中的方法進(jìn)行選擇,選擇的依據(jù)是方法名,方法返回值和方法的參數(shù)列表,所以才叫多分派.而在運(yùn)行期,在靜態(tài)分派已經(jīng)選擇出的方法的基礎(chǔ)上,JVM從實(shí)際類型出發(fā),尋找符合該方法的方法,如果找不到就上升到父類中進(jìn)行查找,這里查找的依據(jù)只有父類這一條路,所以叫單分派.這樣就造成了,對于不同的子類,可能會(huì)由于動(dòng)態(tài)分派選擇到不同的方法去運(yùn)行,也就實(shí)現(xiàn)了多態(tài).
2. 訪問權(quán)限修飾關(guān)鍵字
本類 | 本包 | 子類 | 外部包 | |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
? 訪問權(quán)限的控制是在編譯層的,通過反射還是可以訪問私有成員的
3. Java中的異常
(1). 異常體系
- Throwable:所有錯(cuò)誤或者異常的超類,這個(gè)類或者其子類才能被throw拋出,才能作為catch中的參數(shù)類型
- Error:不應(yīng)該捕獲的嚴(yán)重類型,出現(xiàn)就應(yīng)該退出程序
- VirtulMachineError:虛擬機(jī)錯(cuò)誤(硬件錯(cuò)誤,還是內(nèi)存不夠等等)
- AWTError:AWT是Java用戶界面和繪制圖形圖像的包,這個(gè)錯(cuò)誤多是GUI中產(chǎn)生的
- Exception:通常講的異常,==受檢查異常==,指程序可以處理的異常
- RuntimeException:==運(yùn)行時(shí)異常==,可以不進(jìn)行處理也可以加上try-catch或者throws
- 空指針,數(shù)組越界,類型轉(zhuǎn)換,算數(shù)錯(cuò)誤等等
- IOException:輸入輸出異常,這里代表性的泛指非運(yùn)行時(shí)異常(又稱可檢查異常),必須要顯示的加上try-catch或者throws,否則編譯不通過
- 等等,沒有列舉出全部
- RuntimeException:==運(yùn)行時(shí)異常==,可以不進(jìn)行處理也可以加上try-catch或者throws
- Error:不應(yīng)該捕獲的嚴(yán)重類型,出現(xiàn)就應(yīng)該退出程序
(2). throws和throw關(guān)鍵字
? throws關(guān)鍵字用于在方法后面聲明方法內(nèi)部可能會(huì)拋出的異常.
? throw用于手動(dòng)的拋出異常(通常在try-catch中會(huì)有一些處理后再向外層拋出,具體使用與業(yè)務(wù)邏輯有關(guān))
(3). finally關(guān)鍵字
? 無論是否發(fā)生異常,finally代碼塊中的代碼都會(huì)被執(zhí)行
關(guān)于return和finally的順序:
return語句其實(shí)是先將后面的變量從局部變量區(qū)放入操作數(shù)棧頂,然后執(zhí)行return,返回操作數(shù)棧頂?shù)闹?/p>
finally代碼塊中的代碼執(zhí)行在這兩個(gè)過程之間.也就是說,如果finally代碼塊中沒有出現(xiàn)return語句,是不會(huì)影響方法的返回值的.如果有,那么操作數(shù)棧頂?shù)闹禃?huì)被替換,會(huì)改變方法的返回值.
4. Synchronized詳解
深入理解Java并發(fā)之synchronized實(shí)現(xiàn)原理
(1). Synchronized使用
1). 對象鎖(同步代碼塊)
synchronized (object) {
// 臨界區(qū)代碼
}
? 不同線程訪問同一個(gè)對象的對象鎖,只能有一個(gè)線程成功進(jìn)入,其他線程阻塞在代碼塊外面.當(dāng)該線程退出代碼塊時(shí),其他的線程進(jìn)行CPU的競爭(就緒態(tài)),成功競爭到CPU的線程獲取鎖.
2). 方法鎖(同步方法)
public synchronized method(){
// 整個(gè)方法內(nèi)部都是臨界區(qū)
}
? 不同線程不能同時(shí)進(jìn)入此方法,鎖對象為this,所以多個(gè)線程調(diào)用==同一個(gè)對象的不同同步方法==也會(huì)進(jìn)行同步
? 方法級(jí)的同步是隱式殊轴,即無需通過字節(jié)碼指令來控制的穆役,它實(shí)現(xiàn)在方法調(diào)用和返回操作之中。JVM可以從方法常量池中的方法表結(jié)構(gòu)(method_info Structure) 中的 ACC_SYNCHRONIZED 訪問標(biāo)志區(qū)分一個(gè)方法是否同步方法梳凛。當(dāng)方法調(diào)用時(shí),調(diào)用指令將會(huì) 檢查方法的 ACC_SYNCHRONIZED 訪問標(biāo)志是否被設(shè)置梳杏,如果設(shè)置了韧拒,執(zhí)行線程將先持有monitor(虛擬機(jī)規(guī)范中用的是管程一詞), 然后再執(zhí)行方法十性,最后再方法完成(無論是正常完成還是非正常完成)時(shí)釋放monitor叛溢。在方法執(zhí)行期間,執(zhí)行線程持有了monitor劲适,其他任何線程都無法再獲得同一個(gè)monitor楷掉。
? ==synchronized修飾的方法并沒有monitorenter指令和monitorexit指令,取得代之的確實(shí)是ACC_SYNCHRONIZED標(biāo)識(shí)==霞势,該標(biāo)識(shí)指明了該方法是一個(gè)同步方法烹植,JVM通過該ACC_SYNCHRONIZED訪問標(biāo)志來辨別一個(gè)方法是否聲明為同步方法斑鸦,從而執(zhí)行相應(yīng)的同步調(diào)用。
與sync代碼塊的區(qū)別在于,sync代碼塊的實(shí)現(xiàn)方式實(shí)際上是在代碼塊的開始和結(jié)束處調(diào)用了monitorenter 和 monitorexit 兩個(gè)指令.分別獲取和釋放monitor對象的持有權(quán).
而同步方法中是進(jìn)行了標(biāo)記,沒有使用字節(jié)碼指令,但實(shí)際上還是獲取Monitor對象
3). 類鎖
public MyClass{
public synchronized static void method(){}
}
? 不同的線程不能同時(shí)進(jìn)入這個(gè)類的這個(gè)靜態(tài)方法.使用當(dāng)前類的類對象==MyClass.class為鎖==,所以其他線程只要調(diào)用這個(gè)類其中的任意一個(gè)靜態(tài)同步方法,都會(huì)被阻塞.
(2). Synchronized原理(代碼塊)
1). Java對象模型
? 每一個(gè)Java類在被JVM加載的時(shí)候,JVM都會(huì)給這個(gè)類創(chuàng)建一個(gè)instanceKlass保存在方法區(qū),在JVM層用來表示該Java類.使用new創(chuàng)建一個(gè)對象的時(shí)候,JVM會(huì)創(chuàng)建一個(gè)instanceOopDesc對象,這個(gè)對象中包含了對象頭和實(shí)例數(shù)據(jù)(還會(huì)有填充數(shù)據(jù)來保證每個(gè)對象的內(nèi)存都是8字節(jié)的整數(shù)倍)
? 對象頭包含兩部分:Mark Word(運(yùn)行時(shí)數(shù)據(jù),哈希碼,GC分代年齡,鎖狀態(tài)標(biāo)志,等等)和Klass Point(只想的是對象所屬類的instanceKlass).
? 對象的實(shí)例(instantOopDesc)保存在堆上草雕,對象的元數(shù)據(jù)(instantKlass)保存在方法區(qū)巷屿,對象的引用保存在棧上。
2). 監(jiān)視鎖Monitor
? 每一個(gè)Object對象中都內(nèi)置了一個(gè)Monitor對象.(對象頭中Mark Word中的LockWord指向的是Monitor對象的起始地址)
? Monitor相當(dāng)于許可證,拿到Monitor可以進(jìn)行操作,沒拿到需要等待.
? 在Java虛擬機(jī)中,monitor是由ObjectMonitor實(shí)現(xiàn)的.
ObjectMonitor中有幾個(gè)關(guān)鍵屬性:
- _owner:指向持有Monitor對象的線程
- _WaitSet:存放在該Monitor上處于wait狀態(tài)的線程隊(duì)列(obj.wait())
- _EntryList:存放處于等待鎖block狀態(tài)的線程隊(duì)列
- _recursions:鎖的可重入次數(shù)
- _count:用來記錄當(dāng)前占有鎖的線程的重入次數(shù)
一些操作:
- 線程T等待獲取鎖(同步代碼塊外等待):_EntryList中加入T
- 線程T獲取對象鎖(進(jìn)入代碼塊):_EntryList移除T,_Owner置為T,計(jì)數(shù)器_count+1
- 線程T獲取對象鎖之后調(diào)用了wait()方法:在之前的基礎(chǔ)上給_WaitSet中加入T
3). Synchronized底層
1>. 同步代碼塊
- monitorenter指令插入到同步代碼塊的開始位置
- monitorexit指令插入到同步代碼塊的結(jié)束位置
? JVM保證這兩個(gè)指令是一一對應(yīng)的.
? 當(dāng)線程執(zhí)行到monitorenter時(shí),會(huì)嘗試獲取該對象所對應(yīng)的monitor的所有權(quán).
2>. 同步(靜態(tài))方法
? synchronized方法則會(huì)被翻譯成普通的方法調(diào)用和返回指令如:invokevirtual墩虹、areturn指令.
? 在VM字節(jié)碼層面并沒有任何特別的指令來實(shí)現(xiàn)被synchronized修飾的方法嘱巾,而是在==Class文件的方法表中將該方法的access_flags字段中的synchronized標(biāo)志置為1==,表示該方法是同步方法并==使用調(diào)用該方法的對象或該方法所屬的Class在JVM的內(nèi)部對象表示Klass做為鎖對象==诫钓。
(3). 鎖優(yōu)化
? ==JDK 6==之后對synchronized鎖進(jìn)行優(yōu)化,新增了輕量級(jí)鎖和偏向鎖.
1). 偏向鎖
? “偏向”的意思是旬昭,偏向鎖假定將來只有第一個(gè)申請鎖的線程會(huì)使用鎖(不會(huì)有任何線程再來申請鎖),因此菌湃,只需要在Mark Word中CAS記錄owner(本質(zhì)上也是更新问拘,但初始值為空),如果記錄成功慢味,則偏向鎖獲取成功场梆,記錄鎖狀態(tài)為偏向鎖,以后當(dāng)前線程等于owner就可以零成本的直接獲得鎖纯路;否則或油,說明有其他線程競爭,膨脹為輕量級(jí)鎖驰唬。
? ==記錄線程id,之后這個(gè)線程再次進(jìn)行訪問不需要進(jìn)行同步.當(dāng)其他線程嘗試去獲取這個(gè)鎖時(shí),偏向模式結(jié)束.==
2). 輕量級(jí)鎖
? 使用輕量級(jí)鎖時(shí)顶岸,不需要申請互斥量,僅僅將==Mark Word中的部分字節(jié)CAS更新指向線程棧中的Lock Record(鎖記錄)==,如果更新成功,則輕量級(jí)鎖獲取成功酿炸,記錄鎖狀態(tài)為輕量級(jí)鎖良姆;否則,說明已經(jīng)有線程獲得了輕量級(jí)鎖笤妙,目前發(fā)生了鎖競爭(允許短時(shí)間的鎖競爭,使用==自旋鎖優(yōu)化==),接下來膨脹為重量級(jí)鎖。
- 在代碼進(jìn)入同步塊的時(shí)候世蔗,如果同步對象鎖狀態(tài)為無鎖狀態(tài)(鎖標(biāo)志位為“01”狀態(tài),是否為偏向鎖為“0”)朗兵,虛擬機(jī)首先將==在當(dāng)前線程的棧幀中建立一個(gè)名為鎖記錄(Lock Record)的空間==污淋,用于存儲(chǔ)鎖對象目前的Mark Word的拷貝
- 拷貝對象頭中的==Mark Word復(fù)制到鎖記錄==(Lock Record)中
- 線程嘗試==使用CAS將對象頭中的Mark Word替換為指向鎖記錄的指針==,成功則代表獲得鎖余掖,失敗表示其他線程競爭鎖寸爆,當(dāng)前線程嘗試使用自旋操作來獲取鎖。
- 自旋多次后仍然沒有獲取到鎖,該鎖升級(jí)為重量級(jí)鎖,使用mutex阻塞當(dāng)前線程
3). 自旋鎖
- 當(dāng)前線程競爭鎖失敗時(shí),打算阻塞自己
- 不直接阻塞自己赁豆,而是自旋(空等待仅醇,比如一個(gè)空的有限for循環(huán))一會(huì)
- 在自旋的同時(shí)重新競爭鎖
- 如果自旋結(jié)束前獲得了鎖,那么鎖獲取成功歌憨;否則着憨,自旋結(jié)束后阻塞自己
4). 重量級(jí)鎖
? 在輕量級(jí)鎖自旋一定次數(shù)還沒有競爭到鎖資源時(shí),輕量級(jí)鎖膨脹為重量級(jí)鎖,并阻塞當(dāng)前線程.
? synchronized重量級(jí)鎖本質(zhì)依賴監(jiān)視器鎖monitor實(shí)現(xiàn),而monitor的本質(zhì)是依賴于底層操作系統(tǒng)的Mutex Lock實(shí)現(xiàn),監(jiān)視器鎖可以認(rèn)為直接對應(yīng)底層操作系統(tǒng)中的互斥量(mutex),要進(jìn)行線程之間的切換需要從用戶態(tài)轉(zhuǎn)換成內(nèi)核態(tài),成本非常高.
5. 深拷貝和淺拷貝
? Object對象有個(gè)clone()方法,實(shí)現(xiàn)了對象中各個(gè)屬性的復(fù)制务嫡,但它的可見范圍是protected的甲抖,所以實(shí)體類使用克隆的前提是:
- 實(shí)現(xiàn)Cloneable接口,這是一個(gè)標(biāo)記接口心铃,自身沒有方法准谚。
- 覆蓋clone()方法,可見性提升為public去扣。
? 調(diào)用Object的clone()方法可以返回一個(gè)與當(dāng)前對象完全一樣的拷貝對象.
? 淺拷貝:創(chuàng)建一個(gè)新對象柱衔,然后將當(dāng)前對象的非靜態(tài)字段復(fù)制到該新對象,如果字段是值類型的愉棱,那么對該字段執(zhí)行復(fù)制唆铐;如果該字段是引用類型的話,則復(fù)制引用但不復(fù)制引用的對象奔滑。
? 深拷貝:創(chuàng)建一個(gè)新對象艾岂,然后將當(dāng)前對象的非靜態(tài)字段復(fù)制到該新對象,無論該字段是值類型的還是引用類型朋其,都復(fù)制獨(dú)立的一份王浴。當(dāng)你修改其中一個(gè)對象的任何內(nèi)容時(shí),都不會(huì)影響另一個(gè)對象的內(nèi)容梅猿。
? ==深拷貝和淺拷貝的區(qū)別在于:對對象內(nèi)部的引用是直接復(fù)制還是遞歸的進(jìn)行拷貝.==
6. 線程池
(1). 為什么需要線程池
? 減少線程的創(chuàng)建和銷毀操作,增加復(fù)用
(2). 線程池參數(shù)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize:核心線程數(shù),線程池中至少存活的線程,不會(huì)進(jìn)行銷毀.(關(guān)于超時(shí)時(shí)間可以進(jìn)行設(shè)置是否進(jìn)行銷毀)
- maxumumPoolSize:所有線程總數(shù)上限(核心線程+臨時(shí)線程)
- keepAliveTime:線程最大空閑時(shí)間,線程閑置的時(shí)間到達(dá)這個(gè)時(shí)間會(huì)被銷毀(默認(rèn)不使用于核心線程)
- unit:超時(shí)時(shí)間的單位
- workQueue:任務(wù)隊(duì)列,如果線程池的核心線程沒有空閑,此時(shí)出現(xiàn)了新的任務(wù),新任務(wù)會(huì)被放入這個(gè)隊(duì)列
- 有界隊(duì)列:超出隊(duì)列的上限后會(huì)創(chuàng)建臨時(shí)線程
- 無界隊(duì)列:永遠(yuǎn)不會(huì)創(chuàng)建臨時(shí)線程
- threadFactory:一個(gè)接口對象,用于定義生成線程的方式,如線程名格式
- handler:當(dāng)任務(wù)隊(duì)列滿了,出現(xiàn)新任務(wù)時(shí)的拒絕策略
- ThreadPoolExecutor.AbortPolicy:直接拋出異常氓辣,這是==默認(rèn)策略==
- ThreadPoolExecutor.DiscardPolicy:直接丟棄任務(wù),但是不拋出異常袱蚓。
- ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù)钞啸,然后將新來的任務(wù)加入等待隊(duì)列
- ThreadPoolExecutor.CallerRunsPolicy:由線程池所在的線程處理該任務(wù),比如在 main 函數(shù)中創(chuàng)建線程池喇潘,如果執(zhí)行此策略体斩,將有 main 線程來執(zhí)行該任務(wù)
(3). 幾種封裝好的線程池實(shí)現(xiàn)(不推薦使用,但是很重要)
以下各種實(shí)現(xiàn)都有包含ThreadFactory的構(gòu)造,下面沒有列舉
1). newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
? 一個(gè)==線程數(shù)量固定==的線程池,規(guī)定的最大線程數(shù)量响蓉,超過這個(gè)數(shù)量之后進(jìn)來的任務(wù),會(huì)放到等待隊(duì)列中哨毁,如果有空閑線程枫甲,則在等待隊(duì)列中獲取,遵循先進(jìn)先出原則。
? 核心線程數(shù)和最大線程數(shù)一致
? 默認(rèn)使用的是 LinkedBlockingQueue(無界隊(duì)列) 作為等待隊(duì)列
2). newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
? ==只有一個(gè)線程==的線程池,其他任務(wù)進(jìn)來,會(huì)在等待隊(duì)列中排隊(duì).
? 使用LinkedBlockingQueue(無界隊(duì)列) 作為等待隊(duì)列,可能會(huì)無限長
3). newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
? 緩存型線程池,全部都是臨時(shí)線程.
? ==隊(duì)列中不保存等待任務(wù)==,當(dāng)前沒有空閑線程直接創(chuàng)建新的臨時(shí)線程.臨時(shí)線程的空閑時(shí)間很短.
? 關(guān)鍵在于使用SynchronousQueue作為等待隊(duì)列,它不會(huì)保留任務(wù).
4). newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
? 計(jì)劃型線程池,可以設(shè)置固定時(shí)間的延時(shí)或者定期執(zhí)行任務(wù).
? 使用DelayedWorkQueue 作為等待隊(duì)列,保證隊(duì)列中的任務(wù)只有到了指定的延時(shí)時(shí)間想幻,才會(huì)執(zhí)行任務(wù)粱栖。
(4). 線程池工作原理
- 當(dāng)提交一個(gè)新任務(wù)到線程池時(shí),線程池判斷corePoolSize線程池是否都在執(zhí)行任務(wù)脏毯,如果有空閑線程闹究,則創(chuàng)建一個(gè)新的工作線程來執(zhí)行任務(wù),直到當(dāng)前線程數(shù)等于corePoolSize食店;
- 如果當(dāng)前線程數(shù)為corePoolSize渣淤,繼續(xù)提交的任務(wù)被保存到阻塞隊(duì)列中,等待被執(zhí)行吉嫩;
- 如果阻塞隊(duì)列滿了价认,那就創(chuàng)建新的線程執(zhí)行當(dāng)前任務(wù),直到線程池中的線程數(shù)達(dá)到maxPoolSize自娩,這時(shí)再有任務(wù)來用踩,由飽和策略來處理提交的任務(wù)
7. 反射
與反射機(jī)制相關(guān)的類:
- Class類:類在內(nèi)存中的實(shí)體
- Field類:類的成員變量
- Method類:類的方法
- Constructor類:類的構(gòu)造方法
(1). 獲取Class對象
- Class.forName(className)
(2). 獲取構(gòu)造方法
- Class.getDeclaredConstructors()獲取所有構(gòu)造方法的數(shù)組.(不加Declared不能獲取私有構(gòu)造)
- Class.getDeclaredConstructors(參數(shù)類型數(shù)組也就是Class[])獲取指定參數(shù)的構(gòu)造.(要try-catch,可能找不到)
(3). 調(diào)用構(gòu)造方法
- Constructor.newInstance(參數(shù)1, 參數(shù)2)調(diào)用相應(yīng)構(gòu)造方法
- 如果是私有構(gòu)造,需要進(jìn)行設(shè)置setAccessible(true)
(4). 獲取方法
? 與獲取構(gòu)造方法類似
- Class.getDeclaredMethod(String methodName, Class[] paraTypeArray)獲取指定名稱,參數(shù)的方法
- Class.getDeclaredMethods()獲取全部的方法數(shù)組
(5). 調(diào)用方法
- Method.invoke(參數(shù)1,參數(shù)2,參數(shù)3.......)返回Object
- 私有方法setAccessible(true)
(5). 獲取屬性
- Class.getDeclaredField(String fieldName)根據(jù)屬性名獲取屬性對象
- Class.getDeclaredFields()獲取所有屬性數(shù)組
- 通過set設(shè)置屬性,私有setAccessible(true)
8. 抽象類和接口的區(qū)別
(1). 組成
- 抽象類可以有實(shí)現(xiàn)了的方法,接口不可以有
- 抽象類可以有各種訪問級(jí)別的成員變量,接口只能有public static final的變量
- 抽象類可以有構(gòu)造器(用于子類中調(diào)用以構(gòu)造父類部分的屬性),接口不能
- 抽象類中不能有private的方法,接口中只能有public
(2). 用途
- 抽象類用于表示不可實(shí)例化的類,本質(zhì)上還是類,而接口只是方法的集合,并不是類
- 抽象類只能單繼承,而接口可以實(shí)現(xiàn)多個(gè)
8. 關(guān)于Object.hashcode()方法
? hashCode返回的并不一定是對象的(虛擬)內(nèi)存地址,具體取決于運(yùn)行時(shí)庫和JVM的具體實(shí)現(xiàn)忙迁。
? Object.hashCode是一個(gè)native方法脐彩,看不到源碼。
? Object.hashCode()在JRE中應(yīng)該遵循的一些契約:
一致性姊扔,在程序的一次執(zhí)行過程中惠奸,對==同一個(gè)對象必須一致地返回同一個(gè)整數(shù)==。
如果兩個(gè)對象通過==equals(Object)==比較旱眯,==結(jié)果相等==晨川,那么對這兩個(gè)對象分別調(diào)用==hashCode方法應(yīng)該產(chǎn)生相同的整數(shù)結(jié)果==。
如果兩個(gè)對象通過java.lang.Object.equals(java.lang.Ojbect)比較删豺,==結(jié)果不相等共虑,不必保證對這兩個(gè)對象分別調(diào)用hashCode也返回兩個(gè)不相同的整數(shù)。==
9. JDK個(gè)版本的新特性
java5
- 泛型
- 增強(qiáng)for循環(huán)
- 自動(dòng)封箱拆箱
- 枚舉
- 注解
- 新的線程模型和并發(fā)庫(
java.util.concurrent
)呀页。
java6
- 集合框架增強(qiáng)妈拌。
- 新的數(shù)組拷貝方法。
Arrays.copyOf
和Arrays.copyOfRange
- Scripting. 可以讓其他語言在java平臺(tái)上運(yùn)行蓬蝶。 java6包含了一個(gè)基于Mozilla Rhino實(shí)現(xiàn)的javascript腳本引擎尘分。
- 支持JDBC4.0規(guī)范。
java7
- 二進(jìn)制前綴
0b
或者0B
丸氛。整型(byte, short, int, long)可以直接用二進(jìn)制表示培愁。 - 字面常量數(shù)字的下劃線。用下劃線連接整數(shù)提升其可讀性缓窜,自身無含義定续,不可用在數(shù)字的起始和末尾谍咆。
- 泛型實(shí)例化類型自動(dòng)推斷(new后面跟的不需要注明泛型)。
- try-with-resources語句(帶資源的try)私股。
- 單個(gè)catch中捕獲多個(gè)異常類型(用
|
分割)并通過改進(jìn)的類型檢查重新拋出異常摹察。
java8
- lambada表達(dá)式(Lambda Expressions)。Lambda允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)倡鲸。
- HashMap改進(jìn)供嚎,在鍵值哈希沖突時(shí)能有更好表現(xiàn)。
- Date Time API峭状。加強(qiáng)對日期和時(shí)間的處理克滴。
- java.util 包下的改進(jìn),提供了幾個(gè)實(shí)用的工具類宁炫。
- 并行數(shù)組排序偿曙。
- 標(biāo)準(zhǔn)的==Base64==編解碼。
- 支持無符號(hào)運(yùn)算羔巢。
- HotSpot
- 刪除了 永久代(PermGen).
- 方法調(diào)用的字節(jié)碼指令支持默認(rèn)方法望忆。
代理類的特點(diǎn)java9
- java模塊系統(tǒng) (Java Platform Module System)。
10. Java中基本數(shù)據(jù)類型和其內(nèi)存大小
- 整型
- byte 1字節(jié)
- short 2字節(jié)
- int 4字節(jié)
- long 8字節(jié)
- 字符型
- char 2字節(jié)(ASCII碼和UFT-8,默認(rèn)為'\0')
- 浮點(diǎn)型
- float 4字節(jié)
- double 8字節(jié)
- 布爾型
- boolean (布爾類型比較復(fù)雜,單個(gè)的布爾類型,編譯時(shí)會(huì)被當(dāng)做int類型處理,原因是32位機(jī)一次處理的數(shù)據(jù)量就是4字節(jié).而對于bollean[],會(huì)被轉(zhuǎn)化成byte[],每個(gè)元素占1字節(jié))