最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Java面試必備八股文

2023-06-30 15:38 作者:下班被游戲打-  | 我要投稿
  • 一、Java基礎(chǔ)篇

  • 二、多線程篇

  • 三、JVM篇

  • 四、MYSQL篇

  • 五、Redis系列

  • 六、Spring系列

  • 七、分布式

一、Java基礎(chǔ)篇

1.1)Java有哪幾種數(shù)據(jù)類型

基本數(shù)據(jù)類型:byte(1字節(jié)) short(2字節(jié)) int(4字節(jié)) long(8字節(jié)) float(4字節(jié)) double(8字節(jié)) char(2字節(jié)) boolean(1字節(jié))

引用數(shù)據(jù)類型:String 類 接口 抽象類 枚舉 數(shù)組

1.2)JVM、JRE和JDK的關(guān)系

JVM指的是Java的虛擬機(jī),Java程序需要運(yùn)行在虛擬機(jī)上,不同的平臺都有自己的虛擬機(jī),所以Java語言實(shí)現(xiàn)了跨平臺。


JRE指的是Java的運(yùn)行時(shí)環(huán)境,包括需要的大量的類庫和Java的虛擬機(jī)。


JDK指的運(yùn)行時(shí)候的需要的一些工具類和運(yùn)行時(shí)環(huán)境,比如包括javac.exe ,javadoxc.exe 一系列用于編譯字節(jié)碼工具 打包文檔的工具


1.3)Switch支持的數(shù)據(jù)類型?

jdk1.5之前 byte、short、int、char


jdk5 ~ jdk1.7 加入了enum


jdk1.7之后 加入了String


*注意 不支持long類型


1.4)為什么float=3.4報(bào)錯(cuò)

3.4 默認(rèn)是浮點(diǎn)double類型的,如果賦值給float是向下轉(zhuǎn)型,會出現(xiàn)精度缺失,,需要強(qiáng)制轉(zhuǎn)換


1.5)final 有什么用?

用于修飾類,方法,變量(屬性):


如果修飾類,就是不能夠繼承

如果修飾方法就是不能夠重寫

修飾變量:修飾的變量是不能夠修改的,如果是基本類型那么就是數(shù)值不能修改,如果是引用類型就是地址不能夠修改。

成員變量:必須實(shí)現(xiàn)賦值

局部變量:聲明的時(shí)候可以不賦值,后續(xù)允許一次賦值,賦值之后不能夠修改

1.6)String有哪些特性

首先String是 private final char[]


數(shù)組 所以長度不可變

final 不能夠被繼承

private 內(nèi)容不能夠修改

1.6)Stringbuffer和 Stringbuilder有什么不同?

首先他們都是繼承AbstractStringBuilder,相對于String來說是可變的字符串,只不過Stringbuffer加了synchronized所以是線程安全的,而Stringbuilder是線程非安全的


1.7)== 和 equals 的區(qū)別

== 默認(rèn)是比較兩個(gè)對象的引用地址的,而equals默認(rèn)情況是==比較規(guī)則,但是不同的類會重寫掉Object類的equals從而改變了equals的比較規(guī)則,比如String類的equals方法就是比較他們兩個(gè)的內(nèi)容是否相等


1.8)hashCode和equals

兩個(gè)對象相等他們的hashCode和equals一定相等,但是hashCode相等的兩個(gè)對象未必相等


1.9)方法重載和方法重寫區(qū)別

實(shí)現(xiàn)方式:方法重載是在一個(gè)類當(dāng)中;而方法重寫是在父子類中實(shí)現(xiàn)的

方法重載是方法名字相同,參數(shù)個(gè)數(shù),參數(shù)類型不同。和訪問修飾符 和 返回類型無關(guān);方法重寫是方法名字相同,參數(shù)個(gè)數(shù),參數(shù)類型必須相同,子類的返回值,拋出的異常必須小于等于父類。子類的訪問修飾符大于等于父類。

1.10)面向?qū)ο蠛兔嫦蜻^程的區(qū)別

面向過程:就是具體化的一步一步的去實(shí)現(xiàn),優(yōu)點(diǎn) 就是性能比較快因?yàn)椴恍枰M(jìn)行實(shí)例化。 缺點(diǎn)就是不容易進(jìn)行維護(hù),擴(kuò)展和復(fù)用


面向?qū)ο螅阂驗(yàn)槊嫦驅(qū)ο蟮娜筇攸c(diǎn)就是 封裝、繼承和多態(tài)


封裝就是增加了代碼的安全性,開發(fā)者不用在乎細(xì)節(jié),只知道如何使用就可以了

繼承就是代碼的復(fù)用,結(jié)果設(shè)計(jì)模式就可以達(dá)到已于擴(kuò)展和復(fù)用的特點(diǎn)

多態(tài)使用比較靈活,可以設(shè)計(jì)出低耦合的系統(tǒng)從而便于維護(hù)

1.11)ArrayList 和LinkedList 的區(qū)別

數(shù)據(jù)結(jié)構(gòu):


ArrayList是底層是數(shù)組存儲的,用于一大塊連續(xù)的空間進(jìn)行存儲的,默認(rèn)的初始容量是10 一般情況下當(dāng)容量不夠的時(shí)候會進(jìn)行1.5 倍的一個(gè)擴(kuò)容,因?yàn)槭菙?shù)組形式長度是不變的,所以在擴(kuò)容的時(shí)候需要數(shù)據(jù)的搬遷,從而導(dǎo)致頻繁的擴(kuò)容會導(dǎo)致性能效率,所以我們在使用時(shí)候最好指定好大小。 因?yàn)橛兴饕栽诓檎?、修改?shù)據(jù)時(shí)候都是O(1)時(shí)間復(fù)雜度,而數(shù)據(jù)的增加刪除確要移動后面的元素,所以時(shí)間復(fù)雜度是O(n)。

LinkedList是雙向鏈表的形式存儲的,可以充分用碎片化的空間進(jìn)行存儲,查找,修改數(shù)據(jù)的時(shí)間復(fù)雜度都是O(n),因?yàn)槎际且闅v整個(gè)鏈表。插入和刪除除非是在指定的指針后面下進(jìn)行插入和刪除不然還是要遍歷整個(gè)鏈表。所以說我們通常使用ArrayList進(jìn)行數(shù)據(jù)存儲。

1.12)說一說HashMap數(shù)據(jù)結(jié)構(gòu)

HashMap通常是key-value鍵值對的方式進(jìn)行存儲,在JDK1.7的時(shí)候就是通過數(shù)組+鏈表的形式存儲,每個(gè)數(shù)組存儲的是一個(gè)一個(gè)的Entity組成的鏈表,這些鏈表上的數(shù)字都有一個(gè)特點(diǎn)就是Hash值相同,當(dāng)數(shù)據(jù)量比較大的時(shí)候鏈表的長度比較大,這個(gè)時(shí)候查找的時(shí)間復(fù)雜度就比較大所以。在JDK1.8的時(shí)候引入了紅黑樹概念,當(dāng)一個(gè)鏈表上的長度大于8的時(shí)候并且數(shù)組長度大于64這個(gè)時(shí)候鏈表就自動轉(zhuǎn)換成紅黑樹,如果數(shù)組長度沒有達(dá)到64那么此時(shí)就對數(shù)組進(jìn)行1倍的擴(kuò)容。


而且在JDK1.7和1.8還有一個(gè)改動就是插入的方式,由于JDK1.7的時(shí)候插入方式是頭插法,在多線程的方式下會出選循環(huán)鏈表情況,所以1.8改為了尾插法方式。


擴(kuò)容有三個(gè)地方


初始化數(shù)組長度為0

元素個(gè)數(shù)達(dá)到了 最大個(gè)數(shù)*0.75

單個(gè)鏈表的長度大于8并且數(shù)組長度大于64

HashMap是線程不安全的,如果要保證線程安全那么可以使用ConcurrentHashMap


1.13)ConcurrentHashMap原如何保證的線程安全?

JDK 1.7 時(shí)候是使用分成16個(gè)Seagment段,每個(gè)Seagment里面存儲著一個(gè)HashMap和一個(gè)鎖,所以說1.7能支持最大的并發(fā)量也就是16個(gè)線程


JDK1.8采用的CAS + Synchronized,每次插入的時(shí)候判斷是否是第一次插入,是就通過CAS插入,然后判斷f.hash是否=-1,如果是的那么其他線程在擴(kuò)容,當(dāng)前線程也會參與擴(kuò)容;刪除方法用了synchronized修飾,保障并發(fā)下刪除元素的安全


1.14)抽象類和接口的區(qū)別

繼承:抽象類是只能單繼承的,接口是可以多實(shí)現(xiàn)的


屬性:屬性修飾符也不一樣,抽象累可以是public protect 默認(rèn)不寫 還有final 修飾,但是接口只能是public static final修飾


方法:抽象類既可以抽象的方法,也可以具體的方法,接口只有抽象的方法,而且子類必須實(shí)現(xiàn)


二、多線程篇

2.1) *簡述線程、進(jìn)程的基本概念。以及他們之間關(guān)系是什么

進(jìn)程:是程序的一次執(zhí)行的過程,是系統(tǒng)運(yùn)行的基本單位,其中包含著程序運(yùn)行過程中一些內(nèi)存空間和系統(tǒng)資源。進(jìn)程在運(yùn)行過程中都是相互獨(dú)立,但是線程之間運(yùn)行可以相互影響。

線程:是進(jìn)程的更小的單位。一個(gè)進(jìn)程中包含著多個(gè)線程。和進(jìn)程不同的是線程是共享著進(jìn)程中的內(nèi)存空間和系統(tǒng)資源的。所以在切換線程過程中開銷要比進(jìn)程小的多。

2.2)線程池

*線程池有七個(gè)參數(shù)?

corePoolSize: 線程池核心線程數(shù)最大值


maximumPoolSize: 線程池最大線程數(shù)大小


keepAliveTime: 線程池中非核心線程空閑的存活時(shí)間大小


unit: 線程空閑存活時(shí)間單位


workQueue: 存放任務(wù)的阻塞隊(duì)列


threadFactory: 用于設(shè)置創(chuàng)建線程的工廠,可以給創(chuàng)建的線程設(shè)置有意義的名字,可方便排查問題。


handler: 線程池的飽和策略事件,主要有四種類型。


*線程池的執(zhí)行過程?

當(dāng)提交一個(gè)線程執(zhí)行任務(wù)時(shí)候 ,先看有沒有空閑的核心線程如果有就執(zhí)行,如果沒有就看阻塞隊(duì)列中有沒有滿的狀態(tài),如果沒有放滿則放入隊(duì)列中,否則就直接看線程數(shù)量是否大于非核心線程數(shù)量,如果沒有就直接創(chuàng)建一個(gè)非核心線程,否則就是按照指定的拒絕策略給處理。。如果一個(gè)非核心線程在某個(gè)一段時(shí)間類是空閑的那么線程池就會把這個(gè)線程自動銷毀掉。


四種拒絕策略

AbortPolicy(拋出一個(gè)異常,默認(rèn)的)

DiscardPolicy(直接丟棄任務(wù))

DiscardOldestPolicy(丟棄隊(duì)列里最老的任務(wù),將當(dāng)前這個(gè)任務(wù)繼續(xù)提交給線程池)

CallerRunsPolicy(交給線程池調(diào)用所在的線程進(jìn)行處理)

五種阻塞隊(duì)列 (5)

ArrayBlockingQueue(有界隊(duì)列)是一個(gè)用數(shù)組實(shí)現(xiàn)的有界阻塞隊(duì)列,按FIFO排序量。

LinkedBlockingQueue(可設(shè)置容量隊(duì)列)基于鏈表結(jié)構(gòu)的阻塞隊(duì)列,按FIFO排序任務(wù),容量可以選擇進(jìn)行設(shè)置,不設(shè)置的話,將是一個(gè)無邊界的阻塞隊(duì)列,最大長度為Integer.MAX_VALUE,吞吐量通常要高于ArrayBlockingQuene;newFixedThreadPool線程池使用了這個(gè)隊(duì)列

DelayQueue(延遲隊(duì)列)是一個(gè)任務(wù)定時(shí)周期的延遲執(zhí)行的隊(duì)列。根據(jù)指定的執(zhí)行時(shí)間從小到大排序,否則根據(jù)插入到隊(duì)列的先后排序。newScheduledThreadPool線程池使用了這個(gè)隊(duì)列。

PriorityBlockingQueue(優(yōu)先級隊(duì)列)是具有優(yōu)先級的無界阻塞隊(duì)列;

SynchronousQueue(同步隊(duì)列)一個(gè)不存儲元素的阻塞隊(duì)列,每個(gè)插入操作必須等到另一個(gè)線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于LinkedBlockingQuene,newCachedThreadPool線程池使用了這個(gè)隊(duì)列。

五種創(chuàng)建線程的方式池的方式:

newFixedThreadPool (固定數(shù)目線程的線程池)


newCachedThreadPool(可緩存線程的線程池)


newSingleThreadExecutor(單線程的線程池)


newScheduledThreadPool(定時(shí)及周期執(zhí)行的線程池)


new ThreadPoolExecutor() 自定義的方式創(chuàng)建


使用無界隊(duì)列的線程池會導(dǎo)致內(nèi)存飆升嗎?

會的,newFixedThreadPool使用了無界的阻塞隊(duì)列LinkedBlockingQueue,如果線程獲取一個(gè)任務(wù)后,任務(wù)的執(zhí)行時(shí)間比較長(比如,上面demo設(shè)置了10秒),會導(dǎo)致隊(duì)列的任務(wù)越積越多,導(dǎo)致機(jī)器內(nèi)存使用不停飆升,最終導(dǎo)致OOM。


2.2)線程、進(jìn)程、協(xié)程的區(qū)別

進(jìn)程:進(jìn)程是操作系統(tǒng)分配系統(tǒng)資源和內(nèi)存空間的最小單位。進(jìn)程是獨(dú)立的一塊空間,所以資源和內(nèi)存空間的切換是特別消耗資源的。


線程:線程也叫做輕量級的進(jìn)程,是操作系統(tǒng)調(diào)用執(zhí)行的最小單位。線程的資源是依賴于他的父進(jìn)程,所以他的資源是共享的,線程的切換需要轉(zhuǎn)換到內(nèi)核態(tài)開銷相對于小一些。


協(xié)程:協(xié)程是一種輕量級的線程,協(xié)程是直接在用戶態(tài)就可以控制,具有對內(nèi)核態(tài)來說是不可見的,所以協(xié)程的上下文切換更加的節(jié)約資源消耗。


2.3)什么是上下文的切換

上下文的切換指的是CPU寄存器和程序計(jì)數(shù)器存儲的數(shù)據(jù)進(jìn)行切換,而內(nèi)存數(shù)據(jù)的改變只有在內(nèi)核態(tài)才能進(jìn)行。所以上下文切換對系統(tǒng)來說是巨大的成本。


先是暫停原有的進(jìn)程,保存好進(jìn)程中寄存器中的數(shù)據(jù)在某個(gè)地方

內(nèi)存獲取中下一個(gè)進(jìn)程上下文,存儲到寄存器中

2.4)Java有幾種創(chuàng)建線程的方式

new 一個(gè)Thread

繼承Runnable類

使用Callable

使用線程池

2.5)sleep和wait區(qū)別

sleep 屬于 Thread類,wait屬于Object類

wait會釋放掉鎖,sleep不會釋放鎖

wait必須在同步代碼方法和同步代碼塊中,sleep沒有這一個(gè)限制

wait()要調(diào)用notify()或notifyall()喚醒,sleep()自動喚醒

2.6)Java的內(nèi)存模型

JMM屏蔽了各種硬件和操作系統(tǒng)的內(nèi)存訪問差異,實(shí)現(xiàn)讓Java程序在各平臺都能夠達(dá)到一致的內(nèi)存訪問效果,它定義了Java如何將程序中的變量在主存中讀取


具體定義:所有變量都在主存中,主存是線程的共享區(qū)域,每個(gè)線程都有自己獨(dú)有的工作內(nèi)存,線程想要操作變量必須從主存中copy一份到自己的工作區(qū)域,每個(gè)獨(dú)立內(nèi)存區(qū)域相互隔離。


所以這個(gè)時(shí)候讀寫存在延遲,且不是原子操作,所以就出現(xiàn)了一些列的線程安全操作。比如 原子性、可見性、有序性。

2.6)保證并發(fā)安全的三大特性?

原子性:一次或多次操作在執(zhí)行期間不被其他線程影響


可見性:當(dāng)一個(gè)線程在工作內(nèi)存修改了變量,其他線程能立刻知道**(利用內(nèi)存原子操作解決或者內(nèi)存屏障或者lock前綴)**


有序性:JVM對指令的優(yōu)化會讓指令執(zhí)行順序改變,有序性是禁止指令重排**(內(nèi)存屏障)**


2.7)ThreadLocal原理

每一個(gè)線程創(chuàng)建變量的副本,不同線程間是不可見的,保證線程安全。每個(gè)線程都維護(hù)一個(gè)ThreadLocalMap,key為threadlocal實(shí)例,value是保存的副本。


但是使用ThreadLocal會存在內(nèi)存泄漏問題,因?yàn)閗ey 是弱引用,value是強(qiáng)引用,每次GC時(shí)key都會回收,而value不會被回收。所以為了解決內(nèi)存泄漏問題,可以在每次使用完后刪除value或者使用static修飾ThreadLocal,可以隨時(shí)的獲取value。


第二個(gè)會出現(xiàn)內(nèi)存溢出問題,如果使用的是線程池的方式去使用ThreadLocal話,那么就會出現(xiàn)存儲的value一直存在,這樣就一直堆積。

2.8)什么是CAS鎖

CAS鎖可以保證原子性,思想是更新內(nèi)存是會判斷其內(nèi)存的值是否被修改了,如果沒有被修改就直接更新,如果被修改了,就得重新去獲取值,知道更新為止。這樣是有缺點(diǎn)的:


只能支持一個(gè)變量的原子操作,不能保證整個(gè)代碼塊的原子操作

CAS頻繁的失敗會造成CPU的開銷打

會出現(xiàn)ABA問題

解決ABA問題,可以通過加入版本控制


Java面試必備八股文的評論 (共 條)

分享到微博請遵守國家法律
苍山县| 西安市| 巫溪县| 乌兰察布市| 常州市| 来凤县| 织金县| 通城县| 潮安县| 苍梧县| 德兴市| 保康县| 綦江县| 赣州市| 上杭县| 富阳市| 如东县| 江陵县| 固始县| 罗源县| 富锦市| 灯塔市| 荔浦县| 玛纳斯县| 阿巴嘎旗| 大宁县| 朝阳市| 镇沅| 新密市| 灵石县| 宁明县| 镇远县| 花莲县| 临西县| 广东省| 谷城县| 沐川县| 广安市| 霍林郭勒市| 南雄市| 唐山市|