記一次Java面試問題點總結

来源:https://www.cnblogs.com/zhmlearn/archive/2020/01/20/12201071.html
-Advertisement-
Play Games

引言 昨日接了一個阿裡外包的電話面試,問了一些技術問題感覺到自己是真的菜,接觸Java開發已經也有一段時間,技術方面說來慚愧,一直以來只是局限於框架工具的用法,也沒有進行瞭解其實現的原理,更重要的是一直沒有歸納和總結,這次把這些問題記錄下來,相關的知識點也找了一些資料學習下。 問題 1. Count ...


引言

  昨日接了一個阿裡外包的電話面試,問了一些技術問題感覺到自己是真的菜,接觸Java開發已經也有一段時間,技術方面說來慚愧,一直以來只是局限於框架工具的用法,也沒有進行瞭解其實現的原理,更重要的是一直沒有歸納和總結,這次把這些問題記錄下來,相關的知識點也找了一些資料學習下。

問題

1. CountDownLanch的工作原理

實現原理:計數器的值由構造函數傳入,並用它初始化AQS的state值。當線程調用await方法時會檢查state的值是否為0,如果是就直接返回(即不會阻塞);如果不是,將表示該節點的線程入列,然後將自身阻塞。當其它線程調用countDown方法會將計數器減1,然後判斷計數器的值是否為0,當它為0時,會喚醒隊列中的第一個節點,由於CountDownLatch使用了AQS的共用模式,所以第一個節點被喚醒後又會喚醒第二個節點,以此類推,使得所有因await方法阻塞的線程都能被喚醒而繼續執行。

  引用別人的博客里的一段話,詳細請點擊:Java併發包中CountDownLatch的工作原理、使用示例

題外話: 

什麼是 AQS(抽象的隊列同步器) 
AbstractQueuedSynchronizer類如其名,抽象的隊列式的同步器,AQS定義了一套多線程訪問 共用資源的同步器框架,許多同步類實現都依賴於它,如常用的 ReentrantLock/Semaphore/CountDownLatch。 

 

 

它維護了一個 volatile int state(代表共用資源)和一個 FIFO 線程等待隊列(多線程爭用資源被 阻塞時會進入此隊列)。這裡 volatile 是核心關鍵詞,具體 volatile 的語義,在此不述。state 的 訪問方式有三種: getState() setState()  compareAndSetState()

 

AQS只是一個框架,具體資源的獲取/釋放方式交由自定義同步器去實現,AQS這裡只定義了一個 介面,具體資源的獲取交由自定義同步器去實現了(通過state的get/set/CAS)之所以沒有定義成 abstract,是因為獨占模式下只用實現 tryAcquire-tryRelease,而共用模式下只用實現 tryAcquireShared-tryReleaseShared。如果都定義成abstract,那麼每個模式也要去實現另一模 式下的介面。不同的自定義同步器爭用共用資源的方式也不同。自定義同步器在實現時只需要實 現共用資源 state 的獲取與釋放方式即可,至於具體線程等待隊列的維護(如獲取資源失敗入隊/ 喚醒出隊等),AQS已經在頂層實現好了。自定義同步器實現時主要實現以下幾種方法:
1. isHeldExclusively():該線程是否正在獨占資源。只有用到condition才需要去實現它。

2. tryAcquire(int):獨占方式。嘗試獲取資源,成功則返回true,失敗則返回false。

3. tryRelease(int):獨占方式。嘗試釋放資源,成功則返回true,失敗則返回false。

4. tryAcquireShared(int):共用方式。嘗試獲取資源。負數表示失敗;0 表示成功,但沒有剩餘 可用資源;正數表示成功,且有剩餘資源。

5. tryReleaseShared(int):共用方式。嘗試釋放資源,如果釋放後允許喚醒後續等待結點返回 true,否則返回false。 

AQS定義兩種資源共用方式

1.Exclusive獨占資源 -ReentrantLock Exclusive(獨占,只有一個線程能執行,如ReentrantLock)

2.Share共用資源 -Semaphore/CountDownLatch Share(共用,多個線程可同時執行,如Semaphore/CountDownLatch)。 

3.實現獨占和共用兩種 方式,一般來說,自定義同步器要麼是獨占方法,要麼是共用方式,他們也只需實現 tryAcquiretryRelease、tryAcquireShared-tryReleaseShared 中的一種即可。但 AQS 也支持自定義同步器 同時實現獨占和共用兩種方式,如ReentrantReadWriteLock

 

同步器的實現是ABS核心,以ReentrantLock為例,state初始化為0,表示未鎖定狀態。A線程 lock()時,會調用 tryAcquire()獨占該鎖並將 state+1。此後,其他線程再 tryAcquire()時就會失 敗,直到A線程unlock()到state=0(即釋放鎖)為止,其它線程才有機會獲取該鎖。當然,釋放 鎖之前,A 線程自己是可以重覆獲取此鎖的(state 會累加),這就是可重入的概念。但要註意, 獲取多少次就要釋放多麼次,這樣才能保證state是能回到零態的。 

以CountDownLatch以例,任務分為N個子線程去執行,state也初始化為N(註意N要與 線程個數一致)。這 N 個子線程是並行執行的,每個子線程執行完後 countDown()一次,state 會CAS減1。等到所有子線程都執行完後(即state=0),會unpark()主調用線程,然後主調用線程 就會從await()函數返回,繼續後餘動作。

2. 說一下自旋鎖的原理

如果持有鎖的線程能在很短的時間內釋放鎖資源,那麼那些等待競爭鎖的線程就不需要做內核態和用戶態之間的切換,它們只需要等一等(自旋),等待鎖釋放之後即可立即獲取鎖,這樣避免了用戶線程和內核切換的消耗

線程自旋是需要消耗 cup 的,說白了就是讓 cup 在做無用功,如果一直獲取不到鎖,那線程 也不能一直占用cup自旋做無用功,所以需要設定一個自旋等待的最大時間。
如果持有鎖的線程執行的時間超過自旋等待的最大時間扔沒有釋放鎖,就會導致其它爭用鎖 的線程在最大等待時間內還是獲取不到鎖,這時爭用線程會停止自旋進入阻塞狀態。

自旋鎖的優缺點
自旋鎖儘可能的減少線程的阻塞,這對於鎖的競爭不激烈,且占用鎖時間非常短的代碼塊來 說性能能大幅度的提升,因為自旋的消耗會小於線程阻塞掛起再喚醒的操作的消耗,這些操作會 導致線程發生兩次上下文切換!
但是如果鎖的競爭激烈,或者持有鎖的線程需要長時間占用鎖執行同步塊,這時候就不適合 使用自旋鎖了,因為自旋鎖在獲取鎖前一直都是占用 cpu 做無用功,占著 XX 不 XX,同時有大量 線程在競爭一個鎖,會導致獲取鎖的時間很長,線程自旋的消耗大於線程阻塞掛起操作的消耗, 其它需要cup的線程又不能獲取到cpu,造成cpu的浪費。所以這種情況下我們要關閉自旋鎖;

3. synchronized中類鎖和對象鎖的區別

 這麼基礎的一個問題我竟然遺忘了。。因為之前記的是鎖static方法和非static方法的區別,其實鎖static方法就相當於鎖類class,因為static方法是所有的類共用的,類鎖是鎖當前類的所有實例,對象鎖是鎖當前實例對象,詳細的引入別人的博客:Java鎖Synchronized對象鎖和類鎖的區別

4. volatile關鍵字的作用

     問:說下項目中用到的設計模式

     答:單例模式、責任鏈模式、工程模式、模板模式等等

     問:那你說下你們平常單例模式怎麼實現的

     答:我們用的是雙向檢查

     問:你們雙向檢查有用到volatile吧,那你說下這個關鍵字有什麼作用

     答:它可以用來保證線程每次獲取的對象都是最新狀態

     問:除此之外還有什麼作用

     答: 卒

  真的是

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上面這張表格實際上是一個n行 6列的二維數組。 多維數組的語法: 註意:每一個中括弧表示一個維度。 習題 設計一個程式,可以保存n年的各科成績,可以對這些年的成績進行查詢。 測試用例:保存3年的成績,查詢第三年的生物成績。 ...
  • 很多人都礙於Python培訓班的高昂費用和有限的空餘時間都選擇自學Python,但是沒有老師幫助,顯得有些迷茫,不知應該從何處學起,也不知識看書學習還是應該看視頻學習。本就來談談這個話題。 ...
  • 一、安裝Docker 1、我是虛擬機裝的Centos7,linux 3.10 內核,docker官方說至少3.8以上,建議3.10以上(ubuntu下要linux內核3.8以上) root賬戶登錄,查看內核版本如下 uname -a 2、把yum包更新到最新 yum update (期間要選擇確認, ...
  • 一.常量 聲明常量可以方便代碼的修改,提高復用性. const int maxn=10000; const int N=10000+10; const double exp=1e-6; 同時,聲明常量也可以減少重覆運算,提高代碼速度,例子如下: string s; cin>>s; for(int i ...
  • 發現一個驗證字元串是否包含中文滴時候,一個比正則更好使滴方法,而且是golang 自帶滴驗證。 不需要自己寫正則驗證,代碼如下: package main import ( "fmt" "regexp" "unicode" ) func main() { s1 := "我是中國人hello word ...
  • 基本構架 所有的C程式都有一個 main 函數.其後包含在大括弧中的是 main 函數的內容. main函數是程式的入口,程式運行後,先進入 main 函數,然後一次執行 main 函數體中的語句. 這是一個例子: 簡單來說,寫在 main 中的內容會在程式啟動時執行.main 函數中的內容是程式的 ...
  • 功能描述:做的是物聯網的項目,Excel導入實現的功能是將Excel中的數據批量的導入AEP系統,再導入我們系統中。目前已經完成該功能,前端還會添加進度條優化。Excel模板: 前端向後端傳遞的參數: 前端代碼: <Upload name="wlwDeviceFile" ref="upload" : ...
  • 導入下列依賴包,搞定 sudo apt-get install python3 python-dev python3-dev build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev zlib1g-dev python-pip 上訴 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:本文代碼示例演示瞭如何在WPF中使用LiveCharts庫創建動態條形圖。通過創建數據模型、ViewModel和在XAML中使用`CartesianChart`控制項,你可以輕鬆實現圖表的數據綁定和動態更新。我將通過清晰的步驟指南包括詳細的中文註釋,幫助你快速理解並應用這一功能。 先上效果: 在 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • 概述:本示例演示了在WPF應用程式中實現多語言支持的詳細步驟。通過資源字典和數據綁定,以及使用語言管理器類,應用程式能夠在運行時動態切換語言。這種方法使得多語言支持更加靈活,便於維護,同時提供清晰的代碼結構。 在WPF中實現多語言的一種常見方法是使用資源字典和數據綁定。以下是一個詳細的步驟和示例源代 ...
  • 描述(做一個簡單的記錄): 事件(event)的本質是一個委托;(聲明一個事件: public event TestDelegate eventTest;) 委托(delegate)可以理解為一個符合某種簽名的方法類型;比如:TestDelegate委托的返回數據類型為string,參數為 int和 ...
  • 1、AOT適合場景 Aot適合工具類型的項目使用,優點禁止反編 ,第一次啟動快,業務型項目或者反射多的項目不適合用AOT AOT更新記錄: 實實在在經過實踐的AOT ORM 5.1.4.117 +支持AOT 5.1.4.123 +支持CodeFirst和非同步方法 5.1.4.129-preview1 ...
  • 總說周知,UWP 是運行在沙盒裡面的,所有許可權都有嚴格限制,和沙盒外交互也需要特殊的通道,所以從根本杜絕了 UWP 毒瘤的存在。但是實際上 UWP 只是一個應用模型,本身是沒有什麼許可權管理的,許可權管理全靠 App Container 沙盒控制,如果我們脫離了這個沙盒,UWP 就會放飛自我了。那麼有沒... ...
  • 目錄條款17:讓介面容易被正確使用,不易被誤用(Make interfaces easy to use correctly and hard to use incorrectly)限制類型和值規定能做和不能做的事提供行為一致的介面條款19:設計class猶如設計type(Treat class de ...
  • title: 從零開始:Django項目的創建與配置指南 date: 2024/5/2 18:29:33 updated: 2024/5/2 18:29:33 categories: 後端開發 tags: Django WebDev Python ORM Security Deployment Op ...
  • 1、BOM對象 BOM:Broswer object model,即瀏覽器提供我們開發者在javascript用於操作瀏覽器的對象。 1.1、window對象 視窗方法 // BOM Browser object model 瀏覽器對象模型 // js中最大的一個對象.整個瀏覽器視窗出現的所有東西都 ...