Java工程師面試寶典_第1頁
Java工程師面試寶典_第2頁
Java工程師面試寶典_第3頁
Java工程師面試寶典_第4頁
Java工程師面試寶典_第5頁
已閱讀5頁,還剩144頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論