週五去了一趟深圳某互聯網金融面試,很遺憾吧,沒過,聽到沒過的時候心都碎了,畢竟仍是很想去這家公司的,以後還不要臉的問了「能不能再聊聊」,下樓以後,被二面的經理叫回來講跟架構師聊聊,依舊沒過。。。面試官很好,還給了不少建議,還說要是有合適的會給你聯繫的。回想一下,只能怪本身真的太不爭氣了,沒有藉口!!!基礎!基礎!基礎!html
這個,,,真是個意外,很久沒看到過這個問題了,並且很久沒重寫過equals了,面試官還問「這不是面試常考題麼」,額,我仍是太菜。
主要有兩點:node
(1)不被重寫(原生)的hashCode值是根據內存地址換算出來的一個值。 (2)不被重寫(原生)的equals方法是嚴格判斷一個對象是否相等的方法(object1 == object2)。
常考題還有「==」跟「equals」的區別git
在任什麼時候候,總有一個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區,按照上面的說法,就不會存在內存碎片的問題。
參考:
爲何新生代內存須要有兩個Survivor區github
先來說一下這幾個算法的特性吧
複製:1.將內存分爲兩塊,只用一塊,另外一塊用來說這一塊的對象複製;2.不會產生內存碎片
標記-清除:1.從引用根節點開始標記全部被引用的對象;2.遍歷整個堆,把未標記的對象清除。此算法須要暫停整個應用,同時,會產生內存碎片。
標記-整理:1.從根節點開始標記全部被引用對象;2.遍歷整個堆,把清除未標記對象而且把存活對象「壓縮」到堆的其中一塊,按順序排放。此算法避免了「標記-清除」的碎片問題,同時也避免了「複製」算法的空間問題。
說的有點不夠形象,仍是用對比的表格來展現吧。面試
~ | Mark-Sweep | Mark-Compact | Copying |
---|---|---|---|
速度 | 中等 | 最慢 | 最快 |
空間開銷 | 少(但會堆積碎片) | 少(不堆積碎片) | 一般須要活對象的2倍大小(不堆積碎片) |
移動對象 | 否 | 是 | 是 |
新生代的Minor GC觸發條件:Copying算法就是掃描出存活的對象,並複製到一塊新的徹底未使用的空間中,對應於新生代,就是在Eden和FromSpace或ToSpace之間copy。全部的Minor GC都會觸發全世界的暫停(stop-the-world)
老年代的GC(Major GC/Full GC):老年代與新生代不一樣,老年代對象存活的時間比較長、比較穩定,所以採用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,而後再進行回收未被標記的對象,回收後對用空出的空間要麼進行合併、要麼標記出來便於下次進行分配,總之目的就是要減小內存碎片帶來的效率損耗。redis
有點懵逼,mq只是簡單的瞭解一下,沒想到會到這點。。。留張圖先,後續寫篇大文
算法
參考:ActiveMQ——activemq的詳細說明,queue、topic的區別(精選)spring
很久線程池這一塊了,有點搞亂
shutdown在終止前容許執行之前提交的任務
shutdownNow試圖中止當前正執行的task,並返回還沒有執行的task的list
isShutDown當調用shutdown()方法後返回爲true。
isTerminated當調用shutdown()方法後,而且全部提交的任務完成後返回爲true
awaitTermination當等待超過設定時間時,會監測ExecutorService是否已經關閉,若關閉則返回true,不然返回false數據庫
這題。。。細,太細了編程
int corePoolSize 核心線程數,核心線程會一直存活,即便沒有任務須要執行 int maximumPoolSize 最大線程數 long keepAliveTime 線程空閒時間 TimeUnit unit 指定keepAliveTime的單位,如TimeUnit.SECONDS。當將allowCoreThreadTimeOut設置爲true時對corePoolSize生效。 BlockingQueue<Runnable> workQueue 線程池中的任務隊列 ThreadFactory threadFactory 線程工廠,提供建立新線程的功能。 RejectedExecutionHandler handler 當線程池中的資源已經所有使用,添加新線程被拒絕時,會調用
corePoolSize、maximumPoolSize之間的關係
1.若是線程數量<=核心線程數量,那麼直接啓動一個核心線程來執行任務,不會放入隊列中。 2.若是線程數量>核心線程數,但<=最大線程數,而且任務隊列是LinkedBlockingDeque的時候,超過核心線程數量的任務會放在任務隊列中排隊。 3.若是線程數量>核心線程數,但<=最大線程數,而且任務隊列是SynchronousQueue的時候,線程池會建立新線程執行任務,這些任務也不會被放在任務隊列中。這些線程屬於非核心線程,在任務完成後,閒置時間達到了超時時間就會被清除。 4.若是線程數量>核心線程數,而且>最大線程數,當任務隊列是LinkedBlockingDeque,會將超過核心線程的任務放在任務隊列中排隊。也就是當任務隊列是LinkedBlockingDeque而且沒有大小限制時,線程池的最大線程數設置是無效的,他的線程數最多不會超過核心線程數。 5.若是線程數量>核心線程數,而且>最大線程數,當任務隊列是SynchronousQueue的時候,會由於線程池拒絕添加任務而拋出異常。
參考:
ThreadPoolExecutor線程池參數設置技巧
Java多線程-線程池ThreadPoolExecutor構造方法和規則
此問題保留,改天看源碼寫文章。。。。
-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 輸出版本信息後退出
我有點慌,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
這個真的沒有深刻研究的,寫在簡歷上是但願經過引入新技術(以前一直用的JDK1.6寫的FTP文件服務器),給團隊帶來貢獻的,結果沒有說出來,至關於挖了個坑把本身埋了,好尷尬,先在這放張圖,有空再深刻研究下了。
分佈式鎖是最近剛開始看的問題,知道目前一般實現方式有三種:1.數據庫的共享鎖;2.Redis;3.ZooKeeper,其中Redis的實現方式核心是setnx(set if not exist),只看過一點點Redisson的源碼。面試的時候被問到了,有點慌的其實,畢竟公司沒有項目用到分佈式鎖這種東西,面試官還不一直不信,問我「那大家提工單的時候若是處理點擊屢次的狀況」。
此問題保留,後續會寫一篇RedissonLock源碼的文章。
參考:
Redisson
基於Redis實現分佈式鎖,Redisson使用及源碼分析
Java中的ThreadLocal 變量用於將變量同當前線程綁定,每一個線程都有本身獨立的ThreadLocal變量。這些變量一般用於保存一些變量的狀態信息,譬如用戶信息這種在整個應用中都使用的到而且你不想在每一個方法中都從新聲明。hreadLocal對Key使用到了弱引用,可是爲了保證再也不內存泄露,在每次set.get的時候主動對key==null的entry作遍歷回收。雖然不會形成內存泄露,可是由於只有在每次set,get的時候纔會對entry作key==null的判斷,從而釋放內存,因此可能使大對象在內存中存活很長一段時間,從而佔用內存。因此,咱們在使用完ThreadLocal裏的對象後最好能手動remove一下,或者至少調用下ThreadLocal.set(null)。
參考:
Java併發編程:深刻剖析ThreadLocal
ThreadLocal內存泄露
ThreadLocal內存泄露分析
這個問題,一開始我以爲本身理解仍是足夠的,畢竟本身作過網站,爬蟲還作了很多,可是說出來的時候,跟本身想象中的很不同,這裏再次總結一下吧。因爲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,但是面試的時候,不知道怎麼了,沒有發揮出來,我也是醉了。
參考:
Cookie和session詳解
COOKIE和SESSION有什麼區別?
spring-session簡介、使用及實現原理
這個問題。。。本質上挺好,可是,咱們公司的項目真的沒有技術含量,面試官不信,我都不知道該怎麼回答了,說咱們公司項目很牛逼?可是牛逼在哪裏?全都是增刪改查的項目,緩存還用的ehcache,並且用緩存的地方及其少,JDK還用的1.6。。。把咱們部門的項目給公司其餘部門看,別人說,我覺得我這邊的項目已經夠爛了,沒想到還有更爛的,不想看大家的。離職前還問了咱們組技術最好的項目有沒有技術深度高一點的東西,想了半會,跟我說沒有,我又問了,提工單的時候如何保持一致性的,下面是聊天記錄,能夠看下。其實我也超想挖掘項目中比較高深的東西,可是,咱們作的就是業務系統,我有啥辦法啊。。。
公司的防止重複提交方法,點擊一次後讓它不可點擊。若是瀏覽器壞了發送了兩次請求,須要人工干預。 list[i].disabled = false;
下面是聊天記錄:
總結:
都是基礎,真恨本身平時沒總結,一心只想看架構,結果地基都沒打好,致使面試的時候,樓全面崩塌了。。。。好好反思吧。。。
BTY:
本人目前已離職,若是以爲我還行,,,,,但願各位大佬內推,B輪融資以上的就更好了。。。哦對,座標深圳。
我的網站:http://www.wenzhihuai.com/
個人簡歷:http://www.wenzhihuai.com/myresume.html
GitHub:https://github.com/Zephery