Java常見(jiàn)的面試題

  1)Java 中能創(chuàng)建 volatile 數(shù)組嗎?

創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),姚安企業(yè)網(wǎng)站建設(shè),姚安品牌網(wǎng)站建設(shè),網(wǎng)站定制,姚安網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,姚安網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

  能,Java 中可以創(chuàng)建 volatile 類(lèi)型數(shù)組,不過(guò)只是一個(gè)指向數(shù)組的引用,而不是整個(gè)數(shù)組。我的意思是,如果改變引用指向的數(shù)組,將會(huì)受到 volatile 的保護(hù),但是如果多個(gè)線(xiàn)程同時(shí)改變數(shù)組的元素,volatile 標(biāo)示符就不能起到之前的保護(hù)作用了。

  2)volatile 能使得一個(gè)非原子操作變成原子操作嗎?

  一個(gè)典型的例子是在類(lèi)中有一個(gè) long 類(lèi)型的成員變量。如果你知道該成員變量會(huì)被多個(gè)線(xiàn)程訪(fǎng)問(wèn),如計(jì)數(shù)器、價(jià)格等,你最好是將其設(shè)置為 volatile。為什么?因?yàn)?Java 中讀取 long 類(lèi)型變量不是原子的,需要分成兩步,如果一個(gè)線(xiàn)程正在修改該 long 變量的值,另一個(gè)線(xiàn)程可能只能看到該值的一半(前 32 位)。但是對(duì)一個(gè) volatile 型的 long 或 double 變量的讀寫(xiě)是原子。

  3)volatile 修飾符的有過(guò)什么實(shí)踐?

  一種實(shí)踐是用 volatile 修飾 long 和 double 變量,使其能按原子類(lèi)型來(lái)讀寫(xiě)。double 和 long 都是64位寬,因此對(duì)這兩種類(lèi)型的讀是分為兩部分的,第一次讀取第一個(gè) 32 位,然后再讀剩下的 32 位,這個(gè)過(guò)程不是原子的,但 Java 中 volatile 型的 long 或 double 變量的讀寫(xiě)是原子的。volatile 修復(fù)符的另一個(gè)作用是提供內(nèi)存屏障(memory barrier),例如在分布式框架中的應(yīng)用。簡(jiǎn)單的說(shuō),就是當(dāng)你寫(xiě)一個(gè) volatile 變量之前,Java 內(nèi)存模型會(huì)插入一個(gè)寫(xiě)屏障(write barrier),讀一個(gè) volatile 變量之前,會(huì)插入一個(gè)讀屏障(read barrier)。意思就是說(shuō),在你寫(xiě)一個(gè) volatile 域時(shí),能保證任何線(xiàn)程都能看到你寫(xiě)的值,同時(shí),在寫(xiě)之前,也能保證任何數(shù)值的更新對(duì)所有線(xiàn)程是可見(jiàn)的,因?yàn)閮?nèi)存屏障會(huì)將其他所有寫(xiě)的值更新到緩存。

  4)volatile 類(lèi)型變量提供什么保證?

  volatile 變量提供順序和可見(jiàn)性保證,例如,JVM 或者 JIT為了獲得更好的性能會(huì)對(duì)語(yǔ)句重排序,但是 volatile 類(lèi)型變量即使在沒(méi)有同步塊的情況下賦值也不會(huì)與其他語(yǔ)句重排序。 volatile 提供 happens-before 的保證,確保一個(gè)線(xiàn)程的修改能對(duì)其他線(xiàn)程是可見(jiàn)的。某些情況下,volatile 還能提供原子性,如讀 64 位數(shù)據(jù)類(lèi)型,像 long 和 double 都不是原子的,但 volatile 類(lèi)型的 double 和 long 就是原子的。

  5) 10 個(gè)線(xiàn)程和 2 個(gè)線(xiàn)程的同步代碼,哪個(gè)更容易寫(xiě)?

  從寫(xiě)代碼的角度來(lái)說(shuō),兩者的復(fù)雜度是相同的,因?yàn)橥酱a與線(xiàn)程數(shù)量是相互獨(dú)立的。但是同步策略的選擇依賴(lài)于線(xiàn)程的數(shù)量,因?yàn)樵蕉嗟木€(xiàn)程意味著更大的競(jìng)爭(zhēng),所以你需要利用同步技術(shù),如鎖分離,這要求更復(fù)雜的代碼和專(zhuān)業(yè)知識(shí)。

  6)你是如何調(diào)用 wait()方法的?使用 if 塊還是循環(huán)?為什么?

  wait() 方法應(yīng)該在循環(huán)調(diào)用,因?yàn)楫?dāng)線(xiàn)程獲取到 CPU 開(kāi)始執(zhí)行的時(shí)候,其他條件可能還沒(méi)有滿(mǎn)足,所以在處理前,循環(huán)檢測(cè)條件是否滿(mǎn)足會(huì)更好。下面是一段標(biāo)準(zhǔn)的使用 wait 和 notify 方法的代碼:

  // The standard idiom for using the wait methodsynchronized(obj) {while(condition does not hold)obj.wait(); // (Releases lock, and reacquires on wakeup)... // Perform action appropriate to condition}

  7)什么是多線(xiàn)程環(huán)境下的偽共享(false sharing)?

  偽共享是多線(xiàn)程系統(tǒng)(每個(gè)處理器有自己的局部緩存)中一個(gè)眾所周知的性能問(wèn)題。偽共享發(fā)生在不同處理器的上的線(xiàn)程對(duì)變量的修改依賴(lài)于相同的緩存行,如下圖所示:


  有經(jīng)驗(yàn)程序員的 Java 面試題

  偽共享問(wèn)題很難被發(fā)現(xiàn),因?yàn)榫€(xiàn)程可能訪(fǎng)問(wèn)完全不同的全局變量,內(nèi)存中卻碰巧在很相近的位置上。如其他諸多的并發(fā)問(wèn)題,避免偽共享的最基本方式是仔細(xì)審查代碼,根據(jù)緩存行來(lái)調(diào)整你的數(shù)據(jù)結(jié)構(gòu)。

  8)什么是 Busy spin?我們?yōu)槭裁匆褂盟?

  Busy spin 是一種在不釋放 CPU 的基礎(chǔ)上等待事件的技術(shù)。它經(jīng)常用于避免丟失 CPU 緩存中的數(shù)據(jù)(如果線(xiàn)程先暫停,之后在其他CPU上運(yùn)行就會(huì)丟失)。所以,如果你的工作要求低延遲,并且你的線(xiàn)程目前沒(méi)有任何順序,這樣你就可以通過(guò)循環(huán)檢測(cè)隊(duì)列中的新消息來(lái)代替調(diào)用 sleep() 或 wait() 方法。它唯一的好處就是你只需等待很短的時(shí)間,如幾微秒或幾納秒。LMAX 分布式框架是一個(gè)高性能線(xiàn)程間通信的庫(kù),該庫(kù)有一個(gè) BusySpinWaitStrategy 類(lèi)就是基于這個(gè)概念實(shí)現(xiàn)的,使用 busy spin 循環(huán) EventProcessors 等待屏障。

  9)Java 中怎么獲取一份線(xiàn)程 dump 文件?

  在 Linux 下,你可以通過(guò)命令 kill -3 PID (Java 進(jìn)程的進(jìn)程 ID)來(lái)獲取 Java 應(yīng)用的 dump 文件。在 Windows 下,你可以按下 Ctrl + Break 來(lái)獲取。這樣 JVM 就會(huì)將線(xiàn)程的 dump 文件打印到標(biāo)準(zhǔn)輸出或錯(cuò)誤文件中,它可能打印在控制臺(tái)或者日志文件中,具體位置依賴(lài)應(yīng)用的配置。如果你使用Tomcat。

  10)Swing 是線(xiàn)程安全的?

  不是,Swing 不是線(xiàn)程安全的。你不能通過(guò)任何線(xiàn)程來(lái)更新 Swing 組件,如 JTable、JList 或 JPanel,事實(shí)上,它們只能通過(guò) GUI 或 AWT 線(xiàn)程來(lái)更新。這就是為什么 Swing 提供 invokeAndWait() 和 invokeLater() 方法來(lái)獲取其他線(xiàn)程的 GUI 更新請(qǐng)求。這些方法將更新請(qǐng)求放入 AWT 的線(xiàn)程隊(duì)列中,可以一直等待,也可以通過(guò)異步更新直接返回結(jié)果。你也可以在參考答案中查看和學(xué)習(xí)到更詳細(xì)的內(nèi)容。

  11)什么是線(xiàn)程局部變量?

  線(xiàn)程局部變量是局限于線(xiàn)程內(nèi)部的變量,屬于線(xiàn)程自身所有,不在多個(gè)線(xiàn)程間共享。Java 提供 ThreadLocal 類(lèi)來(lái)支持線(xiàn)程局部變量,是一種實(shí)現(xiàn)線(xiàn)程安全的方式。但是在管理環(huán)境下(如 web 服務(wù)器)使用線(xiàn)程局部變量的時(shí)候要特別小心,在這種情況下,工作線(xiàn)程的生命周期比任何應(yīng)用變量的生命周期都要長(zhǎng)。任何線(xiàn)程局部變量一旦在工作完成后沒(méi)有釋放,Java 應(yīng)用就存在內(nèi)存泄露的風(fēng)險(xiǎn)。

  12)用 wait-notify 寫(xiě)一段代碼來(lái)解決生產(chǎn)者-消費(fèi)者問(wèn)題?

  請(qǐng)參考答案中的示例代碼。只要記住在同步塊中調(diào)用 wait() 和 notify()方法,如果阻塞,通過(guò)循環(huán)來(lái)測(cè)試等待條件。

  13) 用 Java 寫(xiě)一個(gè)線(xiàn)程安全的單例模式(Singleton)?

  請(qǐng)參考答案中的示例代碼,這里面一步一步教你創(chuàng)建一個(gè)線(xiàn)程安全的 Java 單例類(lèi)。當(dāng)我們說(shuō)線(xiàn)程安全時(shí),意思是即使初始化是在多線(xiàn)程環(huán)境中,仍然能保證單個(gè)實(shí)例。Java 中,使用枚舉作為單例類(lèi)是最簡(jiǎn)單的方式來(lái)創(chuàng)建線(xiàn)程安全單例模式的方式。

  14)Java 中 sleep 方法和 wait 方法的區(qū)別?

  雖然兩者都是用來(lái)暫停當(dāng)前運(yùn)行的線(xiàn)程,但是 sleep() 實(shí)際上只是短暫停頓,因?yàn)樗粫?huì)釋放鎖,而 wait() 意味著條件等待,這就是為什么該方法要釋放鎖,因?yàn)橹挥羞@樣,其他等待的線(xiàn)程才能在滿(mǎn)足條件時(shí)獲取到該鎖。

  15)什么是不可變對(duì)象(immutable object)?Java 中怎么創(chuàng)建一個(gè)不可變對(duì)象?

  不可變對(duì)象指對(duì)象一旦被創(chuàng)建,狀態(tài)就不能再改變。任何修改都會(huì)創(chuàng)建一個(gè)新的對(duì)象,如 String、Integer及其它包裝類(lèi)。詳情參見(jiàn)答案,一步一步指導(dǎo)你在 Java 中創(chuàng)建一個(gè)不可變的類(lèi)。

本文名稱(chēng):Java常見(jiàn)的面試題
瀏覽路徑:http://bm7419.com/article2/gejeic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)網(wǎng)站營(yíng)銷(xiāo)、網(wǎng)站制作、網(wǎng)站收錄、虛擬主機(jī)、網(wǎng)頁(yè)設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站