01程序員
談談Java的垃圾回收機制以及觸發時機算法
內存回收機制:就是釋放掉在內存中已經沒有用的對象,要判斷怎樣的對象是沒用的,有兩種方法:數組
(1)採用標記數的方法,在給內存中的對象打上標記,對象被引用一次,計數加一,引用被釋放,計數就減一,當這個計數爲零時,這個對象就能夠被回收,可是,此種方法,對於循環引用的對象是沒法識別出來並加以回收的,數據結構
(2)採用根搜索的方法,從一個根出發,搜索全部的可達對象,則剩下的對象就是可被回收的,垃圾回收是在虛擬機空閒的時候或者內存緊張的時候執行的,何時回收並非由程序員控制的,可達與不可達的概念:分配對象使用new關鍵字,釋放對象時,只需將對象的引用賦值爲null,讓程序不可以在訪問到這個對象,則稱該對象不可達。異步
在如下狀況中垃圾回收機制會被觸發:分佈式
(1)全部實例都沒有活動線程訪問 ;ide
(2)沒有其餘任何實例訪問的循環引用實例;oop
(3)Java中有不一樣的引用類型。判斷實例是否符合垃圾收集的條件都依賴於它的引用類型性能
02網站
推薦系統設計
推薦系統的任務就是聯繫用戶和信息(物品),一方面幫助用戶發現對本身有價值的信息,另外一方面讓信息可以展示在對它感興趣的用戶面前,從而實現信息消費者和信息生產者的共贏。
推薦系統很好知足了用戶、平臺、內容提供商三方的需求。以淘寶爲例:用戶及在淘寶上購物的買家,平臺即淘寶網站,網站上衆多的店主就是內容提供方。經過推薦系統能夠更好將商品曝光給要購買的用戶,提高社會資源的配置效率。
推薦系統落地到業務上須要大量的工程開發:涉及到日誌打點、日誌收集、ETL、分佈式計算、特徵工程、推薦算法建模、數據存儲、提供接口服務、UI展現和交互、推薦效果評估等。
03
Android 實現異步的幾種方式,原理與各自特色
這邊介紹三種:AsyncTask,HandlerThread和IntentService
AsyncTask原理:內部是Handler和兩個線程池實現的,Handler用於將線程切換到主線程,兩個線程池一個用於任務的排隊,一個用於執行任務,當AsyncTask執行execute方法時會封裝出一個FutureTask對象,將這個對象加入隊列中,若是此時沒有正在執行的任務,就執行它,執行完成以後繼續執行隊列中下一個任務,執行完成經過Handler將事件發送到主線程。AsyncTask必須在主線程初始化,由於內部的Handler是一個靜態對象,在AsyncTask類加載的時候他就已經被初始化了。在Android3.0開始,execute方法串行執行任務的,一個一個來,3.0以前是並行執行的。若是要在3.0上執行並行任務,能夠調用executeOnExecutor方法
HandlerThread原理:繼承自Thread,start開啓線程後,會在其run方法中會經過Looper建立消息隊列並開啓消息循環,這個消息隊列運行在子線程中,因此能夠將HandlerThread中的Looper實例傳遞給一個Handler,從而保證這個Handler的handleMessage方法運行在子線程中,Android中使用HandlerThread的一個場景就是IntentService
IntentService原理:繼承自Service,它的內部封裝了HandlerThread和Handler,能夠執行耗時任務,同時由於它是一個服務,優先級比普通線程高不少,因此更適合執行一些高優先級的後臺任務,HandlerThread底層經過Looper消息隊列實現的,因此它是順序的執行每個任務。能夠經過Intent的方式開啓IntentService,IntentService經過handler將每個intent加入HandlerThread子線程中的消息隊列,經過looper按順序一個個的取出並執行,執行完成後自動結束本身,不須要開發者手動關閉
04
簡述幾種排序算法的區別
1.冒泡排序(BubbleSort)
算法簡介:冒泡排序是一種簡單的排序算法。
算法思想:它重複地走訪要排序的數列,一次比較兩個元素,讓較大的數往下沉,較小的往上冒。即:每當兩相鄰的數比較後發現他們的排序與排序要求相反時,就將他們互換。
算法分析:冒泡排序是最慢的排序算法。在實際運用中它是效率最低的算法。可是簡單啊!!!
優勢:穩定
缺點:慢,每次只能移動兩個相鄰的數據。
2.快速排序(QuickSort)
算法簡介:快速排序是一個就地排序,分而治之,大規模遞歸的算法。從本質上來講,它是歸併排序的就地版本。
算法思想:選擇一個基準元素(通常選擇序列最左邊的值做爲基準數據,其實基準的選擇對算法是有影響的),將比基準元素小的元素放在其前面,比基準元素大的元素放在其後面,而後在將小於基準值元素的子數列和大於基準元素的子數列按原來的方法排序,直到整個序列有序。
算法分析:快速排序比大部分排序算法都要快。儘管咱們能夠在某些特殊的狀況下寫出比快速排序快的算法,可是就一般狀況而言,沒有比它更快的了。快速排序是遞歸的,但對於內存很是有限的機器來講,它不是一個好的選擇。
優勢:極快,數據移動少;
缺點:不穩定(在序列越亂的時候,效率越高。在數據有序時,會退化成冒泡排序)
3.歸併排序(MergeSort)
算法簡介:歸併排序是採用分治法(Divide and Conquer)的一個很是典型的應用。
算法思想:首先將初始序列的n個記錄當作是n個有序的子序列,每一個子序列的長度爲1,而後兩兩歸併,獲得n/2個長度爲2的有序子序列,在此基礎上,再對長度爲2的有序子序列進行兩兩歸併,獲得若干個長度爲4的有序子序列,以此類推,直到獲得一個長度爲n的有序序列爲止。
算法分析:歸併排序和選擇排序(包括堆/直接選擇)同樣,歸併排序的性能不受輸入數據的影響,比選擇排序稍微快一點,可是須要多一倍的內存空間,由於它須要一個額外的數組。
優勢:穩定;
缺點:佔內存
4.選擇排序(SelectionSort)
算法簡介:選擇排序也是一種簡單的排序。
算法思想:第一趟:從第一個記錄開始,將後面n-1個記錄進行比較,找到其中最小的記錄和第一個記錄進行交換;第二趟:從第二個記錄開始,將後面n-2個記錄進行比較,找到其中最小的記錄和第2個記錄進行交換;以此類推,直到最後。
算法分析:因此用到它的時候,數據規模越小越好,不管什麼數據進去都是O(n2)的時間複雜度。惟一的好處可能就是不佔用額外的內存空間了吧。
5.堆排序(Heapsort)
算法簡介:堆排序是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。
算法思想:堆排序會將全部的數據建成一個堆,最大的數據在堆頂(此堆爲初始的無序區),而後將堆頂數據和序列的最後一個數據交換,由此獲得新的無序區和有序區,且知足<=的值;接下來再次重建堆(由於交換後新的堆頂可能違反堆的性質,所以須要對當前無序區調整爲新堆),交換數據,依次下去,就能夠排序全部的數據。
算法分析:堆排序適合於數據量很是大的場合(百萬數據)。堆排序不須要大量的遞歸或者多維的暫存數組。這對於數據量很是巨大的序列是合適的。好比超過數百萬條記錄,由於快速排序,歸併排序都使用遞歸來設計算法,在數據量很是大的時候,可能會發生堆棧溢出錯誤。
6.插入排序(InsertSort)
算法簡介:插入排序是一種簡單排序算法。
算法思想:將一個記錄插入到已排序好的有序表中,從而獲得一個新的,記錄數增1的有序表。即先將序列的第一個記錄當作是一個有序的子序列,而後從第二個記錄逐個進行插入,直至整個序列有序爲止。
算法分析:插入排序在實現上,一般採用in-place排序(即只需用到O(1)的額外空間的排序),於是在從後向前掃描過程當中,須要反覆把已排序元素逐步向後挪位,爲最新元素提供插入空間。可是它比冒泡排序快2倍。通常在數據大於1000或重複排序超過200的數據下使用。
優勢:穩定,快
缺點:比較次數不必定,數據重複向後移動。
7.希爾排序(ShellSort)
算法簡介:1959年Shell發明,第一個突破O(n2)的排序算法,是簡單插入排序的改進版。它與插入排序的不一樣之處在於,它會優先比較距離較遠的元素。希爾排序又叫縮小增量排序。
算法思想:先將整個待排序元素序列分割成若干子序列(就是分紅幾個組且個數相同)(由相隔某個「增量」的元素組成的)分別進行直接插入排序,而後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序(由於直接插入排序在元素基本有序的狀況下,效率很高)。其中分組的合理性會對算法產生重要的影響。如今多用D.E.Knuth的分組方法。
算法分析:Shell排序比冒泡排序快5倍,比插入排序大體快2倍。比快排,歸併,堆排慢不少(有時在小數組中比快速排序和堆排序快)。可是它相對比較簡單,它適合於數據量在5000如下而且速度並非特別重要的場合。
8.基數排序(RadixSort)
算法簡介:基數排序和一般的排序算法並不走一樣的路線,它是一種比較新穎的算法。
算法思想:基數排序是按照低位先排序,而後收集;再按照高位排序,而後再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最後的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。
算法分析:它只能用於整數的排序,若是咱們要把一樣的辦法運用到浮點數上,咱們必須瞭解浮點數的存儲格式,並經過特殊的方式將浮點數映射到整數上,而後再映射回去,這是很是麻煩的事情,所以,它的使用一樣也很少。並且,最重要的是,這樣算法也須要較多的存儲空間。
05
談談對運行結果的理解
public static void main(String[] args){int i = 0;System.out.println((i++)+(++i)+(i++)+(++i));System.out.println(i);}
主要是對前++、後++、賦值的理解
int a = i++; // a= 0, i = 1
int b = ++i; // b = 2, i = 2
int c = i++; // c = 2, i = 3
int d = ++i; // d= 4, i = 4
a + b + c + d; // 0 + 2 + 2 + 4 = 8