




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
Java高級工程師面試寶典
JavaSE
多線程
進(jìn)程與線程的區(qū)別?
答:進(jìn)程是所有線程的集合,每一個線程是進(jìn)程中的一條執(zhí)行路徑,線程只
是一條執(zhí)行路徑。
為什么要用多線程?
答:提高程序效率
多線程創(chuàng)建方式?
答:繼承Thread或Runnable接口。
是繼承Thread類好還是實(shí)現(xiàn)Runnable接口好?
答:Runnable接口好,因?yàn)閷?shí)現(xiàn)了接口還可以繼續(xù)繼承。繼承Thread類不能再
繼承。
你在哪里用到了多線程?
答:主要能體現(xiàn)到多線程提高程序效率。
舉例:分批發(fā)送短信、迅雷多線程下載等。
什么是多線程安全?
答:當(dāng)多個線程同時共享,同一個全局變量或靜態(tài)變量,做寫的操作時,可能會發(fā)生數(shù)據(jù)沖突問題,也就
是線程安全問題。做讀操作是不會發(fā)生數(shù)據(jù)沖突問題。
如何解決多線程之間線程安全問題?
答:使用多線程之間同步或使用鎖(Iock)0
為什么使用線程同步或使用鎖能解決線程安全問題呢?
答:將可能會發(fā)生數(shù)據(jù)沖突問題(線程不安全問題),只能讓當(dāng)前一個線程進(jìn)行執(zhí)行。被包裹的代碼執(zhí)行完
成后釋放鎖,讓后才能讓其他線程進(jìn)行執(zhí)行。這樣的話就可以解決線程不安全問題。
什么是多線程之間同步?
答:當(dāng)多個線程共享同一個資源,不會受到其他線程的干擾。
什么是同步代碼塊?
答:就是將可能會發(fā)生線程安全問題的代碼,給包括起來。只能讓當(dāng)前一個
線程進(jìn)行執(zhí)行,被包裹的代碼執(zhí)行完成之后才能釋放所,讓后才能讓其他線程進(jìn)
行執(zhí)行。
多線程同步的分類?
1.使用同步代碼塊?
synchronized(同一個數(shù)據(jù))(
可能會發(fā)生線程沖突問題
privateObjectmutex=newObject();//自定義多線程同步鎖
publicvoidsale(){
synchronized(mutex){
if(trainCount>0){
try(
Thread.sleep(10);
}catch(Exceptione){
}
System.out.printin(Thread.currentThread().getName()+“,出售第"+
(100-trainCount+1)+”張票?”);
trainCount--;}
)
}
2.使用同步函數(shù)
在方法上修飾synchronized稱為同步函數(shù)
publicsynchronizedvoidsale(){
if(trainCount>0){
try{
Thread.steep(40);
}catch(Exceptione){
)
System.out.printin(Thread.currentThread().getName()+',出售第"+
(100-traincount+1)+”張票
trainCount--;
}
}
3.靜態(tài)同步函數(shù)
方法上加上static關(guān)鍵字,使用synchronized關(guān)鍵字修飾為靜態(tài)同步函數(shù)
靜態(tài)的同步函數(shù)使用的鎖是該函數(shù)所屬字節(jié)碼文件對象
同步代碼塊與同步函數(shù)區(qū)別?
答:
同步代碼使用自定鎖(明鎖)
同步函數(shù)使用this鎖
同步函數(shù)與靜態(tài)同步函數(shù)區(qū)別?
注意:有些面試會這樣問:例如現(xiàn)在一個靜態(tài)方法和一個非靜態(tài)靜態(tài)怎么實(shí)現(xiàn)同步?
答:
同步函數(shù)使用this鎖
靜態(tài)同步函數(shù)使用字節(jié)碼文件,也就是類.class
什么是多線程死鎖?
答:
同步中嵌套同步,無法釋放鎖的資源。
解決辦法:同步中盡量不要嵌套同步
Wait()與Notify()區(qū)別?
Wait讓當(dāng)前線程有運(yùn)行狀態(tài)變?yōu)榈却隣顟B(tài),和同步一起使用
Notify喚醒現(xiàn)在正在等待的狀態(tài),和同步一起使用
Wait。與sleep。區(qū)別?
對于sleep。方法,我們首先要知道該方法是屬于Thread類中的。而wait。方法,則是屬于Object類中
的。
sleep。方法導(dǎo)致了程序暫停執(zhí)行指定的時間,讓出cpu該其他線程,但是他的監(jiān)控狀態(tài)依然保持者,當(dāng)
指定的時間到了又會自動恢復(fù)運(yùn)行狀態(tài)。
在調(diào)用sleep。方法的過程中,線程不會釋放對象鎖。
而當(dāng)調(diào)用wait。方法的時候,線程會放棄對象鎖,進(jìn)入等待此對象的等待鎖定池,只有針對此對象調(diào)用
notify。方法后本線程才進(jìn)入對象鎖定池準(zhǔn)備
獲取對象鎖進(jìn)入運(yùn)行狀態(tài)。
Lock與Synchronized區(qū)另!J?
Lock接口可以嘗試非阻塞地獲取鎖當(dāng)前線程嘗試獲取鎖。如果這一時刻鎖沒有被其他線程獲取到,則成
功獲取并持有鎖。
?Lock接口能被中斷地獲取鎖與synchronized不同,獲取到鎖的線程能夠響應(yīng)中斷,當(dāng)獲取到的鎖的
線程被中斷時,中斷異常將會被拋出,同時鎖會被釋放。
Lock接口在指定的截止時間之前獲取鎖,如果截止時間到了依舊無法獲取鎖,則返回。
Condition用法
Condition的功能類似于在傳統(tǒng)的線程技術(shù)中的,Object,wait()和Object,notify()的功能,
代碼:
Conditioncondition=Iock.newCondition();
res.condition.awai10;類似wait
res.Condition.Signal()類似notify
Signala11notifyALL
如何停止線程?
1.使用退出標(biāo)志,使線程正常退出,也就是當(dāng)run方法完成后線程終止。
2.使用stop方法強(qiáng)行終止線程(這個方法不推薦使用,因?yàn)閟top和suspend、resume一樣,也可能
發(fā)生不可預(yù)料的結(jié)果)。
3.使用interrupt方法中斷線程。線程在阻塞狀態(tài)
什么是守護(hù)線程
Java中有兩種線程,一種是用戶線程,另一種是守護(hù)線程。
當(dāng)進(jìn)程不存在或主線程停止,守護(hù)線程也會被停止。
使用setDaemon(true)方法設(shè)置為守護(hù)線程
join()方法作用
join作用是讓其他線程變?yōu)榈却挥挟?dāng)前線程執(zhí)行完畢后,等待的線程才會被釋放。
線程三大特性
多線程有三大特性,原子性、可見性、有序性
原子性:保證數(shù)據(jù)一致性,線程安全。
可見性:對另一個線程是否課件
有序性:線程之間執(zhí)行有順序
說說Java內(nèi)存模型
共享內(nèi)存模型指的就是Java內(nèi)存模型(簡稱JMM),JMM決定一個線程對共享變量的寫入時,
能對另一個線程可見。從抽象的角度來看,JMM定義了線程和主內(nèi)存之間的抽象關(guān)系:線
程之間的共享變量存儲在主內(nèi)存(mainmemory)中,每個線程都有一個私有的本地內(nèi)存
(localmemory),本地內(nèi)存中存儲了該線程以讀/寫共享變量的副本。本地內(nèi)存是JMM的一
個抽象概念,并不真實(shí)存在。它涵蓋了緩存,寫緩沖區(qū),寄存器以及其他的硬件和編譯器優(yōu)
化。
否被龍倒同應(yīng),否就向Java內(nèi)存篌叟—5修
Jvm的存儲構(gòu)傅、棧、方在巨
具,全局費(fèi)蜃
什么是Volatile作用
Volatile關(guān)鍵字的作用是變量在多個線程之間可見。
什么是Atomiclnteger
Atomiclnteger原子類
什么是ThreadLoca
ThreadLocal提高一個線程的局部變量,訪問某個線程擁有自己局部變量。
當(dāng)使用ThreadLocal維護(hù)變量時,ThreadLocal為每個使用該變量的線程提供獨(dú)立的變量副
本,所以每一個線程都可以獨(dú)立地改變自己的副本,而不會影響其它線程所對應(yīng)的副本。
ThreadLocal的接口方法
ThreadLocal類接口很簡單,只有4個方法,我們先來了解一下:
voidset(Objectvalue)設(shè)置當(dāng)前線程的線程局部變量的值。
publicObjectget。該方法返回當(dāng)前線程所對應(yīng)的線程局部變量。
publicvoidremove。將當(dāng)前線程局部變量的值刪除,目的是為了減少內(nèi)存的占用,該方法是
JDK5.0新增的方法。需要指出的是,當(dāng)線程結(jié)束后,對應(yīng)該線程的局部變量將自動被垃圾
回收,所以顯式調(diào)用該方法清除線程的局部變量并不是必須的操作,但它可以加快內(nèi)存回收
的速度。
protectedObjectinitialValue0返回該線程局部變量的初始值,該方法是一個protected的方法,
顯然是為了讓子類覆蓋而設(shè)計(jì)的。這個方法是一個延遲調(diào)用方法,在線程第1次調(diào)用getQ
或set(Object)時才執(zhí)行,并且僅執(zhí)行1次。ThreadLocal中的缺省實(shí)現(xiàn)直接返回一個null。
什么是線程池?
線程池是指在初始化一個多線程應(yīng)用程序過程中創(chuàng)建一個線程集合,然后在需要執(zhí)行新的
任務(wù)時重用這些線程而不是新建一個線程。線程池中線程的數(shù)量通常完全取決于可用內(nèi)存數(shù)
量和應(yīng)用程序的需求。然而,增加可用線程數(shù)量是可能的。線程池中的每個線程都有被分配
一個任務(wù),一旦任務(wù)已經(jīng)完成了,線程回到池子中并等待下一次分配任務(wù)。
線程池作用
基于以下幾個原因在多線程應(yīng)用程序中使用線程是必須的:
1.線程池改進(jìn)了一個應(yīng)用程序的響應(yīng)時間。由于線程池中的線程已經(jīng)準(zhǔn)備好且等待被分配
任務(wù),應(yīng)用程序可以直接拿來使用而不用新建一個線程。
2.線程池節(jié)省了CLR為每個短生存周期任務(wù)創(chuàng)建一個完整的線程的開銷并可以在任務(wù)完
成后回收資源。
3.線程池根據(jù)當(dāng)前在系統(tǒng)中運(yùn)行的進(jìn)程來優(yōu)化線程時間片。
4.線程池允許我們開啟多個任務(wù)而不用為每個線程設(shè)置屬性。
5.線程池允許我們?yōu)檎趫?zhí)行的任務(wù)的程序參數(shù)傳遞一個包含狀態(tài)信息的對象引用。
6.線程池可以用來解決處理一個特定請求最大線程數(shù)量限制問題。
線程池四種創(chuàng)建方式
Java通過Executors(jdkl.5并發(fā)包)提供四種線程池,分別為:
newCachedThreadPool創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收
空閑線程,若無可回收,則新建線程。
newFixedThreadPool創(chuàng)建一個定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會在隊(duì)列中
等待。
newScheduledThreadPool創(chuàng)建一個定長線程池,支持定時及周期性任務(wù)執(zhí)行。
newSingleThreadExecutor創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù),
保證所有任務(wù)按照指定順序(FIFO,LIFO,優(yōu)先級)執(zhí)行。
說說JDK1.5并發(fā)包
名稱作用
Lock鎖
Executors線程池
ReentrantLock一^個可重入的互斥鎖定Lock,功能類似synchronized,
但要強(qiáng)大的多。
ConditionCondition的功能類似于在傳統(tǒng)的線程技術(shù)中
的Qbjectwait。和ObjectnotifyQ的功能,
ConcurrentHashMap分段HasMap
Atomiclnteger原子類
BlockingQueueBlockingQueue通常用于一個線程生產(chǎn)對象,而另外一
個線程消費(fèi)這些對象的場景
ExecutorService執(zhí)行器服務(wù)
鎖的種類
自旋鎖
自旋鎖是采用讓當(dāng)前線程不停地的在循環(huán)體內(nèi)執(zhí)行實(shí)現(xiàn)的,當(dāng)循環(huán)的條件被其他線程改變時
才能進(jìn)入臨界區(qū)。如下
publicclassSpinLock{
privateAtomicReference<Thread>sign=newAtomicReference<>();
publicvoidlock(){
Threadcurrent=Thread.currentThread();
while(!pareAndSet(nulljcurrent)){
}
)
publicvoidunlock(){
Threadcurrent=Thread.currentThread();
pareAndSet(current.null);
)
}
互斥鎖
所謂互斥鎖,指的是一次最多只能有一個線程持有的鎖.在jdkl.5之前,我們通常使用synchronized機(jī)
制控制多個線程對共享資源Lock接口及其實(shí)現(xiàn)類ReentrantLock
可重入鎖
可重入鎖,也叫做遞歸鎖,指的是同一線程外層函數(shù)獲得鎖之后,內(nèi)層遞歸函數(shù)仍然有獲
取該鎖的代碼,但不受影響。
在JAVA環(huán)境下ReentrantLock和synchronized都是可重入鎖
悲觀鎖
.悲觀鎖,正如其名,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部
系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。
悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制(也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證
數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會修
改數(shù)據(jù))。
樂觀鎖
相對悲觀鎖而言,樂觀鎖機(jī)制采取了更加寬松的加鎖機(jī)制。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫
的鎖機(jī)制實(shí)現(xiàn),以保證操作最大程度的獨(dú)占性。但隨之而來的就是數(shù)據(jù)庫性能的大量開銷,
特別是對長事務(wù)而言,這樣的開銷往往無法承受。而樂觀鎖機(jī)制在一定程度上解決了這個
問題。樂觀鎖,大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)
據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個
“version”字段來實(shí)現(xiàn)。讀取出數(shù)據(jù)時,將此版本號一同讀出,之后更新時,對此版本號
加一。此時,將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對,如果
提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。
信號量
信號量(Semaphore),有時被稱為信號燈,是在多線程環(huán)境下使用的一種設(shè)施,它負(fù)責(zé)協(xié)調(diào)各個線程,以
保證它們能夠正確、合理的使用公共資源。
果隹An
網(wǎng)絡(luò)編程
什么是Socket?
Socket就是為網(wǎng)絡(luò)服務(wù)提供的一種機(jī)制。
通訊的兩端都有Sokcet
網(wǎng)絡(luò)通訊其實(shí)就是Sokcet間的通訊
數(shù)據(jù)在兩個Sokcet間通過10傳輸。
TCP與UDP在概念上的區(qū)別
udp:a、是面向無連接,將數(shù)據(jù)及源的封裝成數(shù)據(jù)包中,不需要建立建立連接
b、每個數(shù)據(jù)報的大小在限制64k內(nèi)
c、因無連接,是不可靠協(xié)議
d、不需要建立連接,速度快
tcp:a、建議連接,形成傳輸數(shù)據(jù)的通道.
b、在連接中進(jìn)行大數(shù)據(jù)量傳輸,以字節(jié)流方式
c通過三次握手完成連接,是可靠協(xié)議
d必須建立連接m效率會稍低
設(shè)計(jì)模式
什么是設(shè)計(jì)模式?
設(shè)計(jì)模式(Designpattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)
驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫
無疑問,設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的,設(shè)計(jì)模式使代碼編制真正工程化,設(shè)計(jì)模式
是軟件工程的基石,如同大廈的一塊塊磚石一樣。項(xiàng)目中合理的運(yùn)用設(shè)計(jì)模式可以完美的解決
很多問題,每種模式在現(xiàn)在中都有相應(yīng)的原理來與之對應(yīng),每一個模式描述了一個在我們周圍
不斷重復(fù)發(fā)生的問題,以及該問題的核心解決方案,這也是它能被廣泛應(yīng)用的原因。本章系Java
之美[從菜鳥到高手演變]系列之設(shè)計(jì)模式,我們會以理論與實(shí)踐相結(jié)合的方式來進(jìn)行本章的學(xué)
習(xí),希望廣大程序愛好者,學(xué)好設(shè)計(jì)模式,做一個優(yōu)秀的軟件工程師!
設(shè)計(jì)模式的分類?
總體來說設(shè)計(jì)模式分為三大類:
創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結(jié)構(gòu)型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模
式、享元模式。
行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、
命令模式、備忘錄模式、狀態(tài)模式、訪問者模式、中介者模式、解釋器模式。
其實(shí)還有兩類:并發(fā)型模式和線程池模式。用一個圖片來整體描述一下:
圖設(shè)計(jì)模式之間的關(guān)系
設(shè)計(jì)模式的六大原則
1、開閉原則(OpenClosePrinciple)
開閉原則就是說對擴(kuò)展開放,對修改關(guān)閉。在程序需要進(jìn)行拓展的時候,不能去修改原
有的代碼,實(shí)現(xiàn)一個熱插拔的效果。所以一句話概括就是:為了使程序的擴(kuò)展性好,易于維
護(hù)和升級。想要達(dá)到這樣的效果,我們需要使用接口和抽象類,后面的具體設(shè)計(jì)中我們會提
到這點(diǎn)。
2、里氏代換原則(LiskovSubstitutionPrinciple)
里氏代換原則(LiskovSubstitutionPrincipleLSP)面向?qū)ο笤O(shè)計(jì)的基本原則之一。里氏
代換原則中說,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。LSP是繼承復(fù)用的基石,
只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復(fù)用,而衍
生類也能夠在基類的基礎(chǔ)上增加新的行為。里氏代換原則是對''開-閉"原則的補(bǔ)充。實(shí)現(xiàn)''開
-閉”原則的關(guān)鍵步驟就是抽象化。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里
氏代換原則是對實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。一一FromBaidu百科
3、依賴倒轉(zhuǎn)原則(DependenceInversionPrinciple)
這個是開閉原則的基礎(chǔ),具體內(nèi)容:真對接口編程,依賴于抽象而不依賴于具體。
4、接口隔離原則(InterfaceSegregationPrinciple)
這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。還是一個降低類之間的耦
合度的意思,從這兒我們看出,其實(shí)設(shè)計(jì)模式就是一個軟件的設(shè)計(jì)思想,從大型軟件架構(gòu)出
發(fā),為了升級和維護(hù)方便。所以上文中多次出現(xiàn):降低依賴,降低耦合。
5、迪米特法則(最少知道原則)(DemeterPrinciple)
為什么叫最少知道原則,就是說:一個實(shí)體應(yīng)當(dāng)盡量少的與其他實(shí)體之間發(fā)生相互作用,使
得系統(tǒng)功能模塊相對獨(dú)立。
6、合成復(fù)用原則(CompositeReusePrinciple)
原則是盡量使用合成/聚合的方式,而不是使用繼承。
單例模式
什么是單例模式?
單例保證一個對象JVM中只能有一個實(shí)例,常見單例懶漢式、餓漢式
什么是懶漢式,就是需要的才會去實(shí)例化,線程不安全。
什么是餓漢式,就是當(dāng)class文件被加載的時候,初始化,天生線程安全。
單例寫法
懶漢式代碼
classSingletonTest{
publicstaticvoidmain(String[]args){
Singletonsll=Singleton.getSingLeton();
Singletonsl2=Singleton.getSingLeton0;
System.out.printin(sll==sl2);
}
)
publicclassSingleton{
//當(dāng)需要的才會被實(shí)例化
privatestaticSingletonsingLeton;
privateSingleton(){
}
synchronizedpublicstaticSingletongetSingleton(){
if(singLeton==null){
singLeton=newSingleton();
}
returnsingLeton;
}
)
餓漢式代碼
classSingletonTestl{
publicstaticvoidmain(String[|args){
Singjetonlsll=Singjetonl.getSingfeton();
Sin^etonlsl2=Singjetonl.getSingfeton();
System.oiz£println((sll==sl2)
publicclassSingjetonl{
〃當(dāng)class文件被加載初始化
privatestaticSingletonlsingleton=newSingjetonl0;
privateSingjetonlQ{
publicstaticSingjetonlgetSingJetonQ{
returnsingleton;
工廠模式
什么是工廠模式?
實(shí)現(xiàn)創(chuàng)建者和調(diào)用者分離
簡單工廠代碼
publicinterfaceCar{
publicvoidrun();
)
publicclassAoDiimplementsCar{
@Override
publicvoidrun(){
System.out.println("M^...
}
)
publicinterfaceCar{
publicvoidrun();
}
publicclassCarFactory{
staticpublicCarcreateCar(StringcarName){
Carcar=null;
if(carName.equals("奧迪")){
car=newAoDi();
}elseif(carName.equals("奔馳")){
car=newBenChi();
}
returncar;
)
publicstaticvoidmain(String[]args){
Carcarl=CarFactory.createCar("奧迪”);
Carcar2=CarFactory.createCar("奔馳");
carl.run();
car2.run();
)
}
工廠方法
publicinterfaceCar{
publicvoidrun();
)
publicclassAoDiimplementsCar{
0Override
publicvoidrun(){
System.out.println("奧迪
)
}
publicclassBenChiimplementsCar{
?Override
publicvoidrun(){
System,out.printl/(“奔馳
)
)
publicclassAoDiChiFactory{
staticpublicCarcreateCar(){
returnnewAoDi();
)
}
publicinterfaceBenChiFactory{
staticpublicCarcreateCar(){
returnnewBenChi();
}
)
publicclassMain{
publicstaticvoidmain(String[]args){
Carcl=AoDiChiFactory.createCar();
Carc2=BenChiFactory.createCar();
cl.run();
c2.run();
}
代理模式
什么是代理?
通過代理控制對象的訪問,可以詳細(xì)訪問某個對象的方法,在這個方法調(diào)用處理,或調(diào)用后
處理。既(AOP微實(shí)現(xiàn)),AOP核心技術(shù)面向切面編程。
代理應(yīng)用場景
安全代理可以屏蔽真實(shí)角色
遠(yuǎn)程代理遠(yuǎn)程調(diào)用代理類RMI
延遲加載先加載輕量級代理類,真正需要在加載真實(shí)
代理的分類
靜態(tài)代理(靜態(tài)定義代理類)
動態(tài)代理(動態(tài)生成代理類)
Jdk自帶動態(tài)代理
Cglib、javaassist(字節(jié)碼操作庫)
靜態(tài)代理
靜態(tài)代理需要自己生成代理類
publicclassXiaoMingimplementsHose{
@Override
publicvoidmai(){
System.out.println("我是小明,我要買房啦?。。?!haha");
}
}
classProxyimplementsHose{
privateXiaoMingxiaoMing;
publicProxy(XiaoMingxiaoMing){
this.xiaoMing=xiaoMing;
)
publicvoidmai(){
System.out.printin("我是中介看你買房開始啦!");
xiaoMing.mai();
System.out.printIn("我是中介看你買房結(jié)束啦!");
)
publicstaticvoidmain(String[]args){
Hoseproxy=newProxy(newXiaoMing。);
proxy.mai();
)
}
JDK動態(tài)代理(不需要生成代理類)
實(shí)現(xiàn)InvocationHandler就可以了。
publicinterfaceHose{
/**
*
*@methodDesc:功能描述:(買房代理)
*@author:余勝軍
*@param:
*@createTime:2017年8月27日上午2:54:34
*@returnType:void
*?copyright:上海每特教育科技有限公司
*/
publicvoidmai();
)
publicclassXiaoMingimplementsHose{
@Override
publicvoidmai(){
System.out.printin("我是小明,我要買房啦!?。?!haha");
}
)
publicclassJDKProxyimplementsInvocationHandler{
privateObjecttarjet;
publicODKProxy(Objecttarjet){
this.tarjet=tarjet;
)
0Override
publicObjectinvoke(Objectproxy.Methodmethod,Object[]args)throwsThrowable
{
System.out.printin("我是房產(chǎn)中介開始監(jiān)聽你買房啦!");
Objectoj=method.invoke(tarjetargs);
System.out.printin("我是房產(chǎn)中介結(jié)束監(jiān)聽你買房啦!");
returnoj;
}
}
classTest222{
publicstaticvoidmain(String[]args){
XiaoMingxiaoMing=newXiaoMing();
JDKProxyjdkProxy=newJDKProxy(xiaoMing);
Hosehose=(Hose)
Proxy.neiA/ProxyInstance(xiaoMing.getClass().getClassLoader(),
xiaoMing.getClass().getlnterfaces()jdkProxy);
hose.mai();
)
)
CGLIB動態(tài)代理
實(shí)現(xiàn)
importjava.lang.reflect.Method;
importnet,sf.cglib.proxy.Enhancer;
importnet,sf.cglib.proxy.Methodinterceptor;
importnet.sf.cglib.proxy.MethodProxy;
publicclassCglibimplementsMethodinterceptor{
0Override
publicObjectintercept(Objecto.Methodmethod,Object[]args,MethodProxy
methodProxy)throwsThrowable{
System.out.printlM"我是買房中介,開始監(jiān)聽你買房了???.“);
ObjectinvokeSuper=methodProxy.invokeSuper(Ojargs);
System.out.prilTtln('"我是買房中介,開結(jié)束你買房了???.”);
returninvokeSuper;
}
classTest22222{
publicstaticvoidmain(String[]args){
Cglibcglib=newCglib();
Enhancerenhancer=newEnhancer();
enhancer.setsuperclass(XiaoMing.class);
enhancer.setCallback(cglib);
Hosehose=(Hose)enhancer.create();
hose.mai();
}
}
CGLIB與JDK動態(tài)代理區(qū)別
jdk動態(tài)代理是由Java內(nèi)部的反射機(jī)制來實(shí)現(xiàn)的,cglib動態(tài)代理底層則是借助asm來實(shí)現(xiàn)的。
總的來說,反射機(jī)制在生成類的過程中比較高效,而asm在生成類之后的相關(guān)執(zhí)行過程中比
較高效(可以通過將asm生成的類進(jìn)行緩存,這樣解決asm生成類過程低效問題)。還有一
點(diǎn)必須注意:jdk動態(tài)代理的應(yīng)用前提,必須是目標(biāo)類基于統(tǒng)一的接口。如果沒有上述前提,
jdk動態(tài)代理不能應(yīng)用。
注:asm其實(shí)就是java字節(jié)碼控制.
其他
什么是注解?
Jdk1.5新增新技術(shù),注解。很多框架為了簡化代碼,都會提供有些注解??梢岳斫鉃椴寮?
是代碼級別的插件,在類的方法上寫:@XXX,就是在代碼上插入了一個插件。
注解不會也不能影響代碼的實(shí)際邏輯,僅僅起到輔助性的作用。
注解分類:內(nèi)置注解(也成為元注解jdk自帶注解)、自定義注解(Spring框架)
如何定義一個注解?
代碼:
使用interface定義注解。
?Target(value={ElementType.METHOD^ElementType.TYPE})
gRetention(Retentionpolicy.RU/VTIME)
public@interfaceOneAnnotation{
intbeanld()default0;
StringclassName()default"
String[]arrays();
}
什么是數(shù)據(jù)交換格式?
客戶端與服務(wù)器常用數(shù)據(jù)交換格式xml、json、html
數(shù)據(jù)交換格式用場景
移動端(安卓、I0S)通訊方式采用http協(xié)議+JSON格式走restful風(fēng)格。
很多互聯(lián)網(wǎng)項(xiàng)目都采用Http協(xié)議+JSON
因?yàn)閤ml比較重WebService服務(wù)采用http+xmI格式銀行項(xiàng)目使用比較多
同學(xué)們可以思考下?移動端和PC端服務(wù)器是接口是怎么設(shè)計(jì)的?
服務(wù)q(握*嫉。)一堂功傀邳撬但盛姓口,企用410(8*。線京6?)屏,
Oo采冊分布式、分使供號長
xml:兔不洗朽。@為xml星
多機(jī)、PC、平板
伶.人01r,量假的,8%帶也皎丈。
PCit(電腦經(jīng))夠融排(APP)
所以砧45佬第右中戰(zhàn)率并不
黃后女金黃中
丈村2公曷
webserciexml建打走展0,
json:彩量低,Json匕亮帝4
段J。所以他45融人中etxml
M.o
互解網(wǎng)裝0冊的是Json
Json(數(shù)據(jù)格式抬入)與jsonp(跨柒)/⑥網(wǎng)關(guān)罐口
JSON解析框架有哪些?
fastjson(阿里)、gson(谷歌)、jackson(SpringMVC自帶)
XML解析方式?
Dom4j>Sax、PulI
Dom4j與Sax區(qū)別
dom4j不適合大文件的解析,因?yàn)樗且幌伦訉⑽募虞d到內(nèi)存中,所以有可能出現(xiàn)內(nèi)存
溢出,sax是基于事件來對xml進(jìn)行解析的,所以他可以解析大文件的xml,也正是因?yàn)槿?/p>
此,所以dom4j可以對xml進(jìn)行靈活的增刪改查和導(dǎo)航,而sax沒有這么強(qiáng)的靈活性,所
以sax經(jīng)常是用來解析大型xml文件,而要對xml文件進(jìn)行一些靈活(crud)操作就用dom4j。
XML與JSON區(qū)別
Xml是重量級數(shù)據(jù)交換格式,占寬帶比較大。
JSON是輕量級交換格式,xml占寬帶小。
所有很多互聯(lián)網(wǎng)公司都會使用json作為數(shù)據(jù)交換格式
很多銀行項(xiàng)目,大多數(shù)還是在使用xml。
什么是Java反射
就是正在運(yùn)行,動態(tài)獲取這個類的所有信息。
反射機(jī)制的作用
1,反編譯:.class->.java
2.通過反射機(jī)制訪問java對象的屬性,方法,構(gòu)造方法等;
反射機(jī)制的應(yīng)用場景
Jdbc加載驅(qū)動——
Springioc
框架
反射機(jī)制獲取類有三種方法
〃第一種方式:
Classci=Class.forName("Employee");
//第二種方式:
//java中每個類型都有class屬性.
Classc2=Employee.class;
//第三種方式:
//java語言中任何一個java對象都有g(shù)etClass方法
Employeee=newEmployee();
Classc3=e.getClass();〃c3是運(yùn)行時類(e的運(yùn)行時類是Employee)
反射創(chuàng)建對象的方式
Class<?>forName=Class.forName("coia.itmayiedu.entity.User");
//創(chuàng)建此Class對象所表示的類的一個新實(shí)例調(diào)用了User的無參數(shù)構(gòu)造方法.
Objectnew工nstance=forName.newlnstance();
實(shí)例化有參構(gòu)造函數(shù)
Class<?>forName=Class.forNamecom.itmayiedu.entity.User");
Constructor<?>constructor=forName.getConstructor(String.class,
String.class);
Usernewlnstance=(User)constructor.newlnstance("123",“123”);
反射創(chuàng)建叩i
方法名稱作用
getDeclaredMethods[]獲取該類的所有方法
getReturnType()獲取該類的返回值
getParameterTypesf)獲取傳入?yún)?shù)
getDeclaredFields()獲取該類的所有字段
setAccessible允許訪問私有成員
使用反射為類私有屬性賦值
//獲取當(dāng)前類class地址
Class<?>forName=Class.forName("com.itmayiedu.entity.User");
//使用反射實(shí)例化對象無參數(shù)構(gòu)造函數(shù)
Objectnewlnstance=forName.newlnstance();
//獲取當(dāng)前類的user工d字段
FielddeclaredField=forName.getDeclaredField("userid");
//允許操作私有成員
declaredField.setAccessible(true);
//設(shè)置值
declaredField.set(newlnstance,“123”);
Useruser=(User)newlnstance;
System.out.printin(user.getUserld());
JVM參數(shù)調(diào)優(yōu)
Java虛擬機(jī)原理
所謂虛擬機(jī),就是一臺虛擬的機(jī)器。他是一款軟件,用來執(zhí)行一系列虛擬計(jì)算指令,大體上虛擬機(jī)可以分為
系統(tǒng)虛擬機(jī)和程序虛擬機(jī),大名鼎鼎的VisualBox、Vmare就屬于系統(tǒng)虛擬機(jī),他們完全是對物理計(jì)算的仿真,
提供了一個可以運(yùn)行完整操作系統(tǒng)的軟件平臺。
程序虛擬機(jī)典型代碼就是Java虛擬機(jī),它專門為執(zhí)行單個計(jì)算程序而計(jì)算,在Java虛擬機(jī)中執(zhí)行的指令我們成為Java
自己碼指令。無論是系統(tǒng)虛擬機(jī)還是程序虛擬機(jī),在上面運(yùn)行的軟件都被限制于虛擬機(jī)提供的資源中。
Java發(fā)展至今,出現(xiàn)過很多虛擬機(jī),做初Sun使用的一款叫Classic的:Java虛擬機(jī),到現(xiàn)在引用最廣泛的是HotSpot虛擬
機(jī),除了Sum意外,還有BEA的Jrockit,目前Jrockit和HostSopt都被oralce收入旗下,大有整合的趨勢。
Java內(nèi)存結(jié)構(gòu)
運(yùn)行時數(shù)據(jù)區(qū)
方法區(qū)本地方法棧
MethodAreaNativeMethodStack
語行E■瀚
I隹程序計(jì)數(shù)器
ProgramCounterRegister
執(zhí)行引擎本地庫接口本地方法庫
o由所有線程共享的數(shù)據(jù)區(qū)
O線程隔離的數(shù)據(jù)區(qū)
1、類加載子系統(tǒng):負(fù)責(zé)從文件系統(tǒng)或者網(wǎng)絡(luò)加載Class信息,加載的信息存放在一塊稱之方法區(qū)的內(nèi)存空間。
2、方法區(qū):就是存放類的信息、常量信息、常量池信息、包括字符串字面量和數(shù)字常量等。
3、Java堆:在Java虛擬機(jī)啟動的時候建立Java堆,它是Java程序最主要的內(nèi)存工作區(qū)域,幾乎所有的對象實(shí)例都存放到
Java堆中,堆空間是所有線程共享。
4、直接內(nèi)存:JavaNio庫允許Java程序直接內(nèi)存,從而提高性能,通常直接內(nèi)存速度會優(yōu)于Java堆。讀寫頻繁的場合可能會考慮使用。
5、每個虛擬機(jī)線程都有一個私有棧,一個線程的Java棧在線程創(chuàng)建的時候被創(chuàng)建,Java棧保存著局部變量、方法參數(shù)、同事Java的方法調(diào)用、
返回值等。
6、本地方法棧,最大不同為本地方法棧用于本地方法調(diào)用。Java虛擬機(jī)允許Java直接調(diào)用本地方法(通過使用C語言寫)
7、垃圾收集系統(tǒng)是Java的核心,也是不可少的,Java有一套自己進(jìn)行垃圾清理的機(jī)制,開發(fā)人員無需手工清理,下一節(jié)課詳細(xì)講。
8、PC(ProgramCouneter)寄存器也是每個線程私有的空間,Java虛擬機(jī)會為每個線程創(chuàng)建PC寄存器,在任意時刻,
一個Java線程總是在執(zhí)行一個方法,這個方法稱為當(dāng)前方法,如果當(dāng)前方法不是本地方法,PC寄存器總會執(zhí)行當(dāng)前正在被執(zhí)行的指令,
如果是本地方法,則PC寄存器值為Underfined,寄存器存放如果當(dāng)前執(zhí)行環(huán)境指針、程序技術(shù)器、操作棧指針、計(jì)算的變量指針等信息。
9、虛擬機(jī)核心的組件就是執(zhí)行引擎,它負(fù)責(zé)執(zhí)行虛擬機(jī)的字節(jié)碼,一般戶先進(jìn)行編譯成機(jī)器碼后執(zhí)行。
堆、棧、方法區(qū)概念區(qū)別
Java堆
堆內(nèi)存用于存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內(nèi)存,由java虛擬機(jī)自動垃圾回收器來管理。在堆中產(chǎn)生了一個數(shù)組
或者對象后,還可以在棧中定義一個特殊的變量,這個變量的取值等于數(shù)組或者對象在堆內(nèi)存中的首地址,在棧中的這個特殊
的變量就變成了數(shù)組或者對象的引用變量,以后就可以在程序中使用棧內(nèi)存中的引用變量來訪問堆中的數(shù)組或者對象,引用變
量相當(dāng)于為數(shù)組或者對象起的一個別名,或者代號。
根據(jù)垃圾回收機(jī)制的不同,Java堆有可能擁有不同的結(jié)構(gòu),最為常見的就是將整個Java堆分為
新生代和老年代。其中新聲帶存放新生的對象或者年齡不大的對象,老年代則存放老年對象。
新生代分為den區(qū)、s。區(qū)、si區(qū),S0和s工也被稱為from和to區(qū)域,他們是兩塊大小相等并且可以互相角色的空間。
絕大多數(shù)情況下,對象首先分配在eden區(qū),在新生代回收后,如果對象還存活,則進(jìn)入S0或si區(qū),之后每經(jīng)過一次
新生代回收,如果對象存活則它的年齡就加1,對象達(dá)到一定的年齡后,則進(jìn)入老年代。
Java棧
Java棧是一塊線程私有的空間,一個棧,一般由三部分組成:局部變量表、操作數(shù)據(jù)棧和幀數(shù)據(jù)區(qū)
局部變量表:用于報錯函數(shù)的參數(shù)及局部變量
操作數(shù)棧:主要保存計(jì)算過程的中間結(jié)果,同時作為計(jì)算過程中的變量臨時的存儲空間。
幀數(shù)據(jù)區(qū):除了局部變量表和操作數(shù)據(jù)棧以外,棧還需要一些數(shù)據(jù)來支持常量池的解析,這里幀數(shù)據(jù)區(qū)保存著
訪問常量池的指針,方便計(jì)程序訪問常量池,另外當(dāng)函數(shù)返回或出現(xiàn)異常時賣虛擬機(jī)子必須有一個異常處理表,方便發(fā)送異常
的時候找到異常的代碼,因此異常處理表也是幀數(shù)據(jù)區(qū)的一部分。
局部變量表
操作數(shù)據(jù)棧
幀數(shù)據(jù)區(qū)
Java方法區(qū)
Java方法區(qū)和堆一樣,方法區(qū)是一塊所有線程共享的內(nèi)存區(qū)域,他保存系統(tǒng)的類信息。
比如類的字段、方法、常量池等。方法區(qū)的大小決定系統(tǒng)可以保存多少個類。如果系統(tǒng)
定義太多的類,導(dǎo)致方法區(qū)溢出。虛擬機(jī)同樣會拋出內(nèi)存溢出的錯誤。方法區(qū)可以理解
為永久區(qū)。
虛擬機(jī)參數(shù)配置
什么是虛擬機(jī)參數(shù)配置
在虛擬機(jī)運(yùn)行的過程中,如果可以跟蹤系統(tǒng)的運(yùn)行狀態(tài),那么對于問題的故障
排查會有一定的幫助,為此,在虛擬機(jī)提供了一些跟蹤系統(tǒng)狀態(tài)的參數(shù),使用
給定的參數(shù)執(zhí)行Java虛擬機(jī),就可以在系統(tǒng)運(yùn)行時打印相關(guān)日志,用于分析實(shí)際
問題。我們進(jìn)行虛擬機(jī)參數(shù)配置,其實(shí)就是圍繞著堆、棧、方法區(qū)、進(jìn)行配置。
你說下你熟悉那些jvm參數(shù)調(diào)優(yōu)
堆的參數(shù)配置
-XX:+PrintGC每次觸發(fā)GC的時候打印相關(guān)日志
-XX:+UseSerialGC串行回收
-XX:+PrintGCDetaiIs更詳細(xì)的GC日志
-Xms堆初始值
-Xmx堆最大可用值
-Xmn新生代堆最大可用值
-XX:SurvivorRatio用來設(shè)置新生代中eden空間和from/to空間的比例.
含以-XX:SurvivorRatio=eden/from=den/to
總結(jié):在實(shí)際工作中,我們可以直接將初始的堆大小與最大堆大小相等,
這樣的好處是可以減少程序運(yùn)行時垃圾回收次數(shù),從而提高效率。
-XX:SurvivorRatio用來設(shè)置新生代中eden空間和from/to空間的比例.
設(shè)置最大堆內(nèi)存
參數(shù):-Xms5m-Xmx20m-XX:+PrintGCDetaiIs-XX:+UseSeriaIGC
-XX:+PrintCommandLineFIags
/**
*~ivm參數(shù)設(shè)置
*
*@authorAdministrator
*
*/
publicclass3vmDemo01{
publicstaticvoidmain(String[]args)throwsInterruptedException{
byte[]bl=newbyte[l*1024*1024];
System.out.printIn("分配了Im");
jx/mlnfoO;
Thread.steep(3000);
byte[]b2=newbyte[4*1024*1024];
System,out.printing分配了4m");
Thread.steep(3000);
jx/mlnfoO;
}
/**
*轉(zhuǎn)換為m
*
*@parammaxMemory
*@return
*/
staticprivateStringtoM(longmaxMemory){
floatnum=(float)maxMemory/(1024*1024);
DecimalFormatdf=newDecimalFormat("0.00");//格式化小數(shù)
Strings=df.format(num);//返回的是String類型
returns;
)
staticprivatevoidjvmlnfo(){
〃最大內(nèi)存
longmaxMemory=Runtime.getRuntime().maxMemory();
System.out.printin("maxMemory:"+maxMemory+“,轉(zhuǎn)換為M:"+toM(maxMemory));
//當(dāng)前空閑內(nèi)存
longfreeMemory=Runtime.getRuntime().freeMemory();
System.out.printin("freeMemory:"+freeMemory+",轉(zhuǎn)換為M:"+toAf(freeMemory));
//已經(jīng)使用內(nèi)存
longtotalMemory=Runtime.getRuntime().totalMemory();
System.out.printin("totalMemory:"+totalMemory+"j轉(zhuǎn)換為M''+toM(totalMemory));
)
)
設(shè)置新生代與老年代優(yōu)化參數(shù)
-Xmn新生代大小,一般設(shè)為整個堆的1/3到1/4左右
-XX:SurvivorRatio設(shè)置新生代中eden區(qū)和from/to空間的比例關(guān)系n/1
設(shè)置新生代比例參數(shù)
參數(shù):-Xms20m-Xmx20m-Xmn1m-XX:SurvivorRatio=2-XX:+PrintGCDetaiIs
-XX:+UseSerialGC
publicclassJvmDemo02{
publicstaticvoidmain(String[]args){
//-Xms20m-Xmx20m-Xmnlm-XX:SurvivorRatio=2-XX:+PrintGCDetails-XX:+UseSerialGC
byte[]b=null;
for(inti=0;i<10;i++)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 【課件】+閉合電路的歐姆定律+課件高二上學(xué)期物理人教版(2019)必修第三冊
- 遼寧省沈陽市實(shí)驗(yàn)中學(xué)2024-2025學(xué)年高三下學(xué)期5月月考物理試題(A卷)含解析
- 不安全行為矯正培訓(xùn)課件
- 江西現(xiàn)代職業(yè)技術(shù)學(xué)院《應(yīng)用化學(xué)專業(yè)英語與文獻(xiàn)檢索》2023-2024學(xué)年第二學(xué)期期末試卷
- 吉林省長春吉大附中力旺實(shí)驗(yàn)中學(xué)2024-2025學(xué)年初三英語試題2月月考試題含答案
- 通化師范學(xué)院《廣告與軟文營銷》2023-2024學(xué)年第一學(xué)期期末試卷
- 江蘇信息職業(yè)技術(shù)學(xué)院《中外書籍形態(tài)設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 下學(xué)班會課件
- 山西省大同市平城區(qū)第一中學(xué)2025年高考原創(chuàng)信息試卷化學(xué)試題(四)含解析
- 山西省長治市沁縣2024-2025學(xué)年數(shù)學(xué)三下期末統(tǒng)考模擬試題含解析
- 4-12現(xiàn)場鋼筋直螺紋加工質(zhì)量檢驗(yàn)記錄
- 室內(nèi)零星維修工程施工方案
- 2023天地偉業(yè)安防產(chǎn)品技術(shù)參數(shù)和檢測報告
- 特種設(shè)備(機(jī)電類)生產(chǎn)單位安全風(fēng)險管控(日管控、周排查、月調(diào)度)清單
- 火龍罐聯(lián)合耳穴壓豆治療失眠個案護(hù)理
- 冀教版數(shù)學(xué)四年級下冊《用字母表示數(shù)》專項(xiàng)訓(xùn)練卷
- 書香茶社茶館創(chuàng)業(yè)計(jì)劃書
- 大學(xué)生創(chuàng)新創(chuàng)業(yè)教程(高職)PPT完整全套教學(xué)課件
- 《大隨求陀羅尼》羅馬拼音與漢字對照版
- 基于arduino的無線傳感器網(wǎng)絡(luò)室內(nèi)定位方法的研究畢業(yè)論文
- 心肺復(fù)蘇及AED的使用
評論
0/150
提交評論