作者:Zephery鏈接:http://www.wenzhihuai.com


目錄

  1. 重寫equals爲什麼要重寫hashCode
  2. JVM中survivor區存在的意義是啥
  3. minor gc、major gc、full gc使用了哪種垃圾回收算法,爲什麼
  4. mq中的queue和topic有什麼區別
  5. 線程池中shutdown、shutdownNow、isShutdown、isTerminated、awaitTermination的使用場景
  6. 使用new ThreadPoolExecutor()中裏面的幾個參數含義以及使用場景(maximumPoolSize超了會怎樣)
  7. ConcurrentHashMap中Segment的作用,還有用了什麼鎖
  8. tail -f中f的含義
  9. df -h中h的含義
  10. fastdfs原理
  11. 分佈式鎖原理與實現方式,如果保持一致性,秒殺架構中會加1000把鎖?
  12. threadlocal有何缺陷
  13. cookie和session的原理,分佈式場景下如何保持唯一。
  14. 你對你們公司項目有什麼深入的理解麼?
週五去了一趟深圳某互聯網金融面試,很遺憾吧,沒過,聽到沒過的時候心都碎了,畢竟還是很想去這家公司的,之後還不要臉的問了“能不能再聊聊”,下樓之後,被二面的經理叫回來說跟架構師聊聊,依舊沒過。。。面試官很好,還給了很多建議,還說要是有合適的會給你聯繫的。回想一下,只能怪自己真的太不爭氣了,沒有藉口!!!基礎!基礎!基礎!

1.重寫equals爲什麼要重寫hashCode

這個…..真是個意外,好久沒看到過這個問題了,而且好久沒重寫過equals了,面試官還問“這不是面試常考題麼”,額,我還是太菜。

主要有兩點:

  1. 不被重寫(原生)的hashCode值是根據內存地址換算出來的一個值。
  2. 不被重寫(原生)的equals方法是嚴格判斷一個對象是否相等的方法(object1 == object2)。
  3. 常考題還有“==”跟“equals”的區別

2.JVM中survivor區存在的意義是啥

在任何時候,總有一個survivor space是empty的,在下一次coping collection時,會將eden和另一個survivor space裏的live object copy到這個裏面。

live objects在兩個survivor space裏copy來copy去,直到對象old enough可以放到tenured generation裏(copy 過去的)

因爲在垃圾收集的時候需要將dead object清理掉,如果只有一個survivor區,那麼這個survivor區裏的dead object在清理掉之後就會產生內存碎片,爲了避免內存碎片那麼必須將live object移動來移動去,這樣就會損失性能。

如果有兩個survivor區,按照上面的說法,就不會存在內存碎片的問題。

參考:http://blog.csdn.net/antony9118/article/details/51425581

3.minor gc、major gc、full gc使用了哪種垃圾回收算法,爲什麼

先來講一下這幾個算法的特性吧

  1. 複製:1.將內存分爲兩塊,只用一塊,另一塊用來講這一塊的對象複製;2.不會產生內存碎片
  2. 標記-清除:1.從引用根節點開始標記所有被引用的對象;2.遍歷整個堆,把未標記的對象清除。此算法需要暫停整個應用,同時,會產生內存碎片。
  3. 標記-整理:1.從根節點開始標記所有被引用對象;2.遍歷整個堆,把清除未標記對象並且把存活對象“壓縮”到堆的其中一塊,按順序排放。此算法避免了“標記-清除”的碎片問題,同時也避免了“複製”算法的空間問題。

說的有點不夠形象,還是用對比的表格來展示吧。


Java 面試總結


  1. 新生代的Minor GC觸發條件:Copying算法就是掃描出存活的對象,並複製到一塊新的完全未使用的空間中,對應於新生代,就是在Eden和FromSpace或ToSpace之間copy。所有的Minor GC都會觸發全世界的暫停(stop-the-world)
  2. 老年代的GC(Major GC/Full GC):老年代與新生代不同,老年代對象存活的時間比較長、比較穩定,因此採用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,然後再進行回收未被標記的對象,回收後對用空出的空間要麼進行合併、要麼標記出來便於下次進行分配,總之目的就是要減少內存碎片帶來的效率損耗。

4.mq中的queue和topic有什麼區別

有點懵逼,mq只是簡單的瞭解一下,沒想到會到這點。。。留張圖先,後續寫篇大文


Java 面試總結


參考:https://www.cnblogs.com/lemon-flm/p/7676047.html

5.線程池中shutdown、shutdownNow、isShutdown、isTerminated、awaitTermination的使用場景

好久沒做線程池這一塊了,有點亂

  1. shutdown在終止前允許執行以前提交的任務
  2. shutdownNow試圖停止當前正執行的task,並返回尚未執行的task的list
  3. isShutDown當調用shutdown()方法後返回爲true。
  4. isTerminated當調用shutdown()方法後,並且所有提交的任務完成後返回爲true
  5. awaitTermination當等待超過設定時間時,會監測ExecutorService是否已經關閉,若關閉則返回true,否則返回false

6.使用new ThreadPoolExecutor()中裏面的幾個參數含義以及使用場景(maximumPoolSize超了會怎樣)

這題…..細,太細了

  1. int corePoolSize 核心線程數,核心線程會一直存活,即使沒有任務需要執行
  2. int maximumPoolSize 最大線程數
  3. long keepAliveTime 線程空閒時間
  4. TimeUnit unit 指定keepAliveTime的單位,如TimeUnit.SECONDS。當將allowCoreThreadTimeOut設置爲true時對corePoolSize生效。
  5. BlockingQueue
  6. workQueue 線程池中的任務隊列
  7. ThreadFactory threadFactory 線程工廠,提供創建新線程的功能。
  8. RejectedExecutionHandler handler 當線程池中的資源已經全部使用,添加新線程被拒絕時,會調用

corePoolSize、maximumPoolSize之間的關係

  1. 如果線程數量<=核心線程數量,那麼直接啓動一個核心線程來執行任務,不會放入隊列中。
  2. 如果線程數量>核心線程數,但<=最大線程數,並且任務隊列是LinkedBlockingDeque的時候,超過核心線程數量的任務會放在任務隊列中排隊。
  3. 如果線程數量>核心線程數,但<=最大線程數,並且任務隊列是SynchronousQueue的時候,線程池會創建新線程執行任務,這些任務也不會被放在任務隊列中。這些線程屬於非核心線程,在任務完成後,閒置時間達到了超時時間就會被清除。
  4. 如果線程數量>核心線程數,並且>最大線程數,當任務隊列是LinkedBlockingDeque,會將超過核心線程的任務放在任務隊列中排隊。也就是當任務隊列是LinkedBlockingDeque並且沒有大小限制時,線程池的最大線程數設置是無效的,他的線程數最多不會超過核心線程數。
  5. 如果線程數量>核心線程數,並且>最大線程數,當任務隊列是SynchronousQueue的時候,會因爲線程池拒絕添加任務而拋出異常。
參考:https://www.cnblogs.com/waytobestcoder/p/5323130.htmlhttp://blog.csdn.net/qq_25806863/article/details/71126867

7. ConcurrentHashMap中Segment的作用,還有用了什麼鎖

此問題保留,改天看源碼寫文章。。。。

8.tail -f中f的含義

-c, --bytes=N 輸出最後N個字節-F 等同於--follow=name --retry,根據文件名進行追蹤,並保持重試,即該文件被刪除或改名後,如果再次創建相同的文件名,會繼續追蹤-f, --follow[={name|descriptor}] 根據文件描述符進行追蹤,當文件改名或被刪除,追蹤停止; -f, --follow以及 --follow=descriptor 都是相同的意思-n, --lines=N 輸出最後N行,而非默認的最後10行--max-unchanged-stats=N 參看texinfo文檔(默認爲5)--max-consecutive-size-changes=N 參看texinfo文檔(默認爲200)--pid=PID 與-f合用,表示在進程ID,PID死掉之後結束.-q, --quiet, --silent 從不輸出給出文件名的首部-s, --sleep-interval=S 與-f合用,表示在每次反覆的間隔休眠S秒-v, --verbose 總是輸出給出文件名的首部--help 顯示幫助信息後退出--version 輸出版本信息後退出

9.df -h中h的含義

我有點慌,df --help看了下我還是記不住那麼多….

-a, --all 全部文件系統列表-B, --block-size=SIZE 使用SIZE大小的Blocks-h, --human-readable 以可讀性較高的方式來顯示信息-H, --si 與-h參數相同,但在計算時是以1000 Bytes爲換算單位而非1024 Bytes;-i, --inodes 顯示inode的信息;-k 指定區塊大小爲1024字節;跟--block-size=1K一樣-l, --local 僅顯示本地端的文件系統;--no-sync 在取得磁盤使用信息前,不要執行sync指令,此爲預設值;-P, --portability 使用POSIX的輸出格式;--sync 在取得磁盤使用信息前,先執行sync指令;-t, --type=TYPE 僅顯示指定文件系統類型的磁盤信息;-T, --print-type 顯示文件系統的類型;-x, --exclude-type=TYPE 不要顯示指定文件系統類型的磁盤信息;-v (ignored)--help display this help and exit--version output version information and exit

10. fastdfs原理

這個真的沒有深入研究的,寫在簡歷上是希望通過引入新技術(之前一直用的JDK1.6寫的FTP文件服務器),給團隊帶來貢獻的,結果沒有說出來,相當於挖了個坑把自己埋了,好尷尬,先在這放張圖,有空再深入研究下了。


Java 面試總結


11.分佈式鎖原理與實現方式,如果保持一致性,秒殺架構中會加1000把鎖?

分佈式鎖是最近剛開始看的問題,知道目前通常實現方式有三種:

  1. 數據庫的共享鎖;
  2. Redis;
  3. ZooKeeper.

其中Redis的實現方式核心是setnx(set if not exist),只看過一點點Redisson的源碼。面試的時候被問到了,有點慌的其實,畢竟公司沒有項目用到分佈式鎖這種東西,面試官還不一直不信,問我“那你們提工單的時候如果處理點擊多次的情況”。

此問題保留,後續會寫一篇RedissonLock源碼的文章。

參考:https://github.com/redisson/redissonhttp://blog.jobbole.com/99751/

12.threadlocal有何缺陷

Java中的ThreadLocal 變量用於將變量同當前線程綁定,每個線程都有自己獨立的ThreadLocal變量。這些變量通常用於保存一些變量的狀態信息,譬如用戶信息這種在整個應用中都使用的到並且你不想在每個方法中都重新聲明。

hreadLocal對Key使用到了弱引用,但是爲了保證不再內存泄露,在每次set.get的時候主動對key==null的entry做遍歷回收。雖然不會造成內存泄露,但是因爲只有在每次set,get的時候纔會對entry做key==null的判斷,從而釋放內存,所以可能使大對象在內存中存活很長一段時間,從而佔用內存。

所以,我們在使用完ThreadLocal裏的對象後最好能手動remove一下,或者至少調用下ThreadLocal.set(null)。

參考:www.cnblogs.com/dolphin0520/p/3920407.htmlhttp://www.importnew.com/22480.htmlhttp://liuinsect.iteye.com/blog/1827012

13.cookie和session的原理,分佈式場景下如何保持唯一。

這個問題,一開始我覺得自己理解還是足夠的,畢竟自己做過網站,爬蟲還做了不少,但是說出來的時候,跟自己想象中的很不一樣,這裏再次總結一下吧。

由於HTTP是無狀態的協議,一旦數據交換完畢,客戶端和服務器的連接就會關閉,如果需要重新連接,那麼久必須發起新的會話。所以,在客戶端和服務器中保存相關的信息是通過cookie和session來實現的。

簡單的來說,session存儲於服務端,cookie存在於客戶端,每次會話時服務器會在內存中開闢一小塊內存空間記錄會話,session的運行依賴於session id(tomcat中叫jsessionid),而session id是存儲在cookie中的,如果瀏覽器禁用了cookie,那麼session也會失效,以大部分登錄網站爲例,可以試試登錄之後禁用cookie,刷新頁面,登錄信息沒了,之後是再怎麼登錄也登錄不進去。所以,需要記錄的點是:

  1. session存儲在服務端,cookie存儲在客戶端(瀏覽器);
  2. 服務端中記錄唯一會話標示用的是session id,tomcat中叫做jsessionid,cookie中保存session id,發送請求的時候攜帶sessionid
  3. session存放的位置一般放在服務器的內存中,分佈式環境下一般都是用spring-session和redis構建。
  4. cookie安全性差,一般採用加密。而且不能跨域。

分佈式環境下如何保存,公司採用的還是memcache,新項目都換成了redis集羣。公司的不是我負責的,但是,我自己的項目用到了spring-session和redis,可是面試的時候,不知道怎麼了,沒有發揮出來,我也是醉了。


Java 面試總結


參考:www.cnblogs.com/linguoguo/p/5106618.htmlhttps://www.zhihu.com/question/19786827http://blog.csdn.net/wojiaolinaaa/article/details/62424642

14.你對你們公司項目有什麼深入的理解麼?

這個問題…..本質上挺好,但是,我們公司的項目真的沒有技術含量,面試官不信,我都不知道該怎麼回答了,說我們公司項目很牛逼?但是牛逼在哪裏?全都是增刪改查的項目,緩存還用的ehcache,而且用緩存的地方及其少,JDK還用的1.6。。。把我們部門的項目給公司其他部門看,別人說,我以爲我這邊的項目已經夠爛了,沒想到還有更爛的,不想看你們的。

離職前還問了我們組技術最好的項目有沒有技術深度高一點的東西,想了半會,跟我說沒有,我又問了,提工單的時候如何保持一致性的,下面是聊天記錄,可以看下。其實我也超想挖掘項目中比較高深的東西,但是,我們做的就是業務系統,我有啥辦法啊….

公司的防止重複提交方法,點擊一次後讓它不可點擊。如果瀏覽器壞了發送了兩次請求,需要人工幹預。list[i].disabled = false;

下面是聊天記錄:


Java 面試總結


Java 面試總結


Java 面試總結


總結:

都是基礎,真恨自己平時沒總結,一心只想看架構,結果地基都沒打好,導致面試的時候,樓全面崩塌了……好好反思吧….

相關文章