寫給正在找工作的你
都說金三銀四,對於找工作的人來說,因為每年的三月或四月是不少互聯網公司的年終季,不少人都是拿到年終獎后不滿意,或者感覺職業發展受限,之后跑路。這樣不少部門因為人員流動,就會有hc空缺出來。
這里要說的是每年3、4月份確實是hc最多的季節,但同時是跳槽旺季,競爭大,你要想找到好的坑位,那就需要絕對的實力才行。
相對來說,其實年底是個好時候,俗話說,鐵打的營盤流水的兵,互聯網的陣地上不少崗位是常年招人,常年缺人,當然hc並不富裕,但是年底的時候,看機會的人也少。畢竟不少人還是很在意“年終獎”的嘛。所以說,年底跳槽你可能會損失一部分年終獎,但換工作的競爭性相對來說也會少很多,競爭的人少了嘛,說不定你就可以憑“運氣的實力”脫穎而出呢?
快手面試
算法
面試官很親切,說Excel表用過吧,Excel表中的編號一般是這樣的,A....Z AA...AZ BA...BZ,分別對應數字0...25 26....51 52...77,類比做數字映射,給出一個字符串,求映射的結果。
分析 這個題目其實很基礎,可以理解為是以26為基准的進制轉換,一個for循環,除了末尾的字符直接加到結果上之外,其他的字符位-'A'+1的結果乘以26*(該字符位置與末尾的差值)。做這種題目一定要先思考,自己手動實現一下。
如果想看具體代碼答案,可以掃碼關注【程序員之道】,后台回復“快手列轉換”。
第二個算法,就稍微有一點偏了,如何實現redis的分布式鎖。
如果沒有接觸過高並發,或者沒有使用過redis作為分布式鎖,那這這個算法肯定是寫不出來的,而且像這種算法,一般來說可能也就是讓講講思路。具體實現確實有點難。
關於分布式鎖,其實是有幾個坑的:
- 加鎖,必須設置過期時間(防止釋放鎖失敗,有過期時間,鎖可以自動釋放)。且加鎖和設置過期時間必須為原子操作。否則,如果加鎖成功,但設置過期時間時客戶端崩潰,那設置過期時間就失敗了。
- 加鎖和釋放鎖必須是同一個客戶端。用唯一id來標志。
- 釋放鎖時,判斷鎖是否屬於自己及釋放鎖必須是原子操作。
思考了這些,你能寫成正確的加鎖,解鎖方式嗎?具體的坑及正確的加解鎖方式,關注【程序員之道】,后台回復“redis分布式鎖”。
基礎
- mysql索引怎么建立,查詢語句select * from T where a="a" and b="b" and c="c",與select * from T where a="a" and c="c" and b="b"執行有什么區別嗎?建議索引遵循什么原則?
要點:
(1)盡量減少like,但不是絕對不可用,”xxxx%” 是可以用到索引的
(2)表的主鍵、外鍵必須有索引
(3 誰的區分度更高(同值的最少),誰建索引,區分度的公式是count(distinct(字段))/count(*)
(4)單表數據太少,不適合建索引
(5)where,order by ,group by 等過濾時,后面的字段最好加上索引
(6)如果既有單字段索引,又有這幾個字段上的聯合索引,一般可以刪除聯合索引;
(7)聯合索引的建立需要進行仔細分析;盡量考慮用單字段索引代替:
(8)聯合索引: mysql 從左到右的使用索引中的字段,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是key index(a,b,c). 可以支持 a|a,b|a,b,c 3種組合進行查找,但不支持 b,c 進行查找.當最左側字段是常量引用時,索引就十分有效。
(9)前綴索引: 有時候需要索引很長的字符列,這會讓索引變得大且慢。通常可以索引開始的部分字符,這樣可以大大節約索引空間,從而提高索引效率。其缺點是不能用於ORDER BY和GROUP BY操作,也不能用於覆蓋索引 Covering index(即當索引本身包含查詢所需全部數據時,不再訪問數據文件本身)。
(10)NULL會導致索引形同虛設
=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式。
-
redis里有哪些數據結構,都用過什么?redis里Sorted Set怎么用,需要傳什么參數?
要點:
redis的數據結構:String,Hash、List、Set、Sorted Set,用過哪些就說哪些就行了,沒用過的,估計你根據名詞也能大概猜出是什么。
面試官問Sorted Set大概是你聽到你說了Sorted Set,所以問一下你命令,看你是不是真的知道啊,不知道的話,這下沒法蒙混過關了吧。有序集合,設置每個key的時候需要傳入一個score參數。具體命令zadd key score value。還有一些其他的命令google學習一下吧! -
java volatile干什么用的。public int incrment() { count++},兩個線程同時訪問是否有問題,count如果用volatile修飾呢?
要點:
volatile主要是保證多線程訪問時的可見性。我們知道計算機為了提高訪問內存的速度,引入了工作內存和主內存的概率,多線程訪問數據時,訪問的是工作內存的數據,各個線程之間的工作內存是分別隔離的。這就可能導致同一個變量,由於工作內存的存在,在不同線程“看到的值”是不一樣的。但volatile關鍵字,強制了各線程讀取變量時必須從主內存讀取,同時對變量的修改也直接刷新到主內存,這樣就保證了同一變量修改的同時可以立刻被其他線程“看到”。這里面使用了“內存屏障”的技術。
對於count++,操作系統執行時,並不是一個原子操作,分為三步:1)將count變量load到內存。2)執行count+1。3)將結果存入內存。非原子性操作,任何一個步驟執行的時候,都可能被其他線程打斷,所以多線程執行時會有問題。
使用volatile修飾也是不可以的,因為始終不是原子操作,也只是保證可見性而已,原子性的問題無法解決。 -
jvm里內存分配什么樣的,分別用來干什么?
要點:
JVM內存分配幾乎是每個java開發人員的面試必考點,單純這部分的內容都夠寫幾個篇章的了。這里只是簡單的介紹一下。
JVM內存分為年輕代和老年代,其中年輕代又分為S0、S1、Eden區,JVM采用分代垃圾回收算法,因為這樣才能更充分的利用年輕代和老年代的對象特點,最大化的提高垃圾回收效率。 -
類對象定義后分配在年輕代。
-
大對象或大數組直接分配在老年代。
常見的垃圾回收算法有復制算法、標記清除、標記整理,然后又引出不同的垃圾回收器,垃圾回收器的迭代是不斷發現問題並優化的過程,新生代收集器使用的收集器:Serial、PraNew、Parallel Scavenge;老年代收集器使用的收集器:Serial Old、Parallel Old、CMS。然后結合自己的理解再說一下!
-
jvm的棧是做什么,為什么有堆又有棧,只使用堆可以嗎?
要點:
JVM的棧是線程私有的,一些基本變量都是存儲在棧中的,Java棧中存放的是一個個的棧幀,每個棧幀對應一個被調用的方法,在棧幀中包括局部變量表(Local Variables)、操作數棧(Operand Stack)、指向當前方法所屬的類的運行時常量池(運行時常量池的概念在方法區部分會談到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息。當線程執行一個方法時,就會隨之創建一個對應的棧幀,並將建立的棧幀壓棧。當方法執行完畢之后,便會將棧幀出棧。
為什么有了堆之后還要有棧?棧的存在可以說是為了解決遞歸調用的問題。如果只有堆內存,那就不會有遞歸調用了。 -
分布式自增id怎么實現,如果用redis實現,怎么保證與數據庫的一致性?
分布式自增id一般使用MySQL的自增id、redis的incr函數,還有比較經典的雪花算法。
MySQL自增id受數據庫訪問速度的限制,在分布式使用時qps不大。
使用redis產生自增id,就要防止redis崩潰的可能性,一般在MySQL或hbase中記錄當前最大的value值。或者如果你設計的是一個聊天室,那肯定是有持久化存儲當前聊天室的最大seqId,如果redis集群出現崩潰,從持久化存儲的地方取出最大seqId然后自增即可。 -
ArrayList,LinkedList有什么區別,分別什么時候使用?
ArrayList的底層實現是數組,數組的擴容是不斷通過復制來完成的,所以存儲的數據容量不斷發生變化時,ArrayList的性能是比較差的。使用ArrayList時一般都是預知數據的最大容量。如果能直接使用數組,那使用數組當然是最好的了。
LinkedList的底層實現是鏈表,發生數據擴容時,性能較好,但同容量情況下占用的空間比ArrayList要大。對於數據頻繁擴容的情況,推薦使用LinkedList。
面試的內容還有很多,限於篇幅問題,在下一篇介紹。
程序員的小伙伴們,覺得自己孤單么,那就加入公眾號[程序員之道],一起交流溝通,走出我們的程序員之道!