-
線程和進程的區別
根本區別:進程是操作系統資源分配的基本單位,而線程是任務調度和執行的基本單位
在開銷方面:每個進程都有獨立的代碼和數據空間(程序上下文),程序之間的切換會有較大的開銷;線程可以看做輕量級的進程,同一類線程共享代碼和數據空間,每個線程都有自己獨立的運行棧和程序計數器(PC),線程之間切換的開銷小。
所處環境:在操作系統中能同時運行多個進程(程序);而在同一個進程(程序)中有多個線程同時執行(通過CPU調度,在每個時間片中只有一個線程執行)
內存分配方面:系統在運行的時候會爲每個進程分配不同的內存空間;而對線程而言,除了CPU外,系統不會爲線程分配內存(線程所使用的資源來自其所屬進程的資源),線程組之間只能共享資源。
包含關係:沒有線程的進程可以看做是單線程的,如果一個進程內有多個線程,則執行過程不是一條線的,而是多條線(線程)共同完成的;線程是進程的一部分,所以線程也被稱爲輕權進程或者輕量級進程。 -
垃圾收集講一下,1.8有哪些新特性
深入理解JVM垃圾收集機制(JDK1.8)
JDK1.8 十大新特性詳解 -
tcp和udp,tcp網絡架構
TCP與UDP的對比
TCP/IP架構
TCP/IP五層網絡架構及OSI參考模型 -
數組兩數之和返回最接近k的值
java中給定整形數組,輸出該數組中和數值2最接近的元素
數組-(sum close)找到數組中和與k最接近的3個數字 -
反射了解嗎class.forname和classloader區別
在Java的反射中,Class.forName和ClassLoader的區別 -
synchronized和lock的區別
兩者區別:
1.首先synchronized是java內置關鍵字,在jvm層面,Lock是個java類;
2.synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖;
3.synchronized會自動釋放鎖(a 線程執行完同步代碼會釋放鎖 ;b 線程執行過程中發生異常會釋放鎖),Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖;
4.用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會一直等待下去,而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了;
5.synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平(兩者皆可)
6.Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題。
public class Test {
static Object o1 = new Object();
static Object o2 = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
synchronized (o1) {
System.out.println("線程1鎖o1");
try {
Thread.sleep(1000);//讓當前線程睡眠,保證讓另一線程得到o2,防止這個線程啓動一下連續獲得o1和o2兩個對象的鎖。
synchronized (o2) {
System.out.println("線程1鎖o2");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
synchronized (o2) {
System.out.println("線程2鎖o2");
synchronized (o1) {
System.out.println("線程2鎖o1");
}
}
}
}).start();
}
}
上面的代碼就是一個完整的死鎖程序,程序中有兩個線程,線程1鎖住了o1,獲得鎖之後休眠1秒鐘,這個時候線程2鎖住了o2,也進行休眠操作。
線程1休眠完了之後去鎖o2,但是o2已經被線程2給鎖住了,這邊只能等待,同樣的道理,線程2休眠完之後也要去鎖o1,同樣也會等待,這樣死鎖就產生了。
-
死鎖的條件
死鎖產生的4個必要條件
1、互斥:某種資源一次只允許一個進程訪問,即該資源一旦分配給某個進程,其他進程就不能再訪問,直到該進程訪問結束。
2、佔有且等待:一個進程本身佔有資源(一種或多種),同時還有資源未得到滿足,正在等待其他進程釋放該資源。
3、不可搶佔:別人已經佔有了某項資源,你不能因爲自己也需要該資源,就去把別人的資源搶過來。
4、循環等待:存在一個進程鏈,使得每個進程都佔有下一個進程所需的至少一種資源。
當以上四個條件均滿足,必然會造成死鎖,發生死鎖的進程無法進行下去,它們所持有的資源也無法釋放。這樣會導致CPU的吞吐量下降。所以死鎖情況是會浪費系統資源和影響計算機的使用性能的。那麼,解決死鎖問題就是相當有必要的了。 -
避免死鎖的方法
產生死鎖需要四個條件,那麼,只要這四個條件中至少有一個條件得不到滿足,就不可能發生死鎖了。由於互斥條件是非共享資源所必須的,不僅不能改變,還應加以保證,所以,主要是破壞產生死鎖的其他三個條件。
a、破壞“佔有且等待”條件
方法1:所有的進程在開始運行之前,必須一次性地申請其在整個運行過程中所需要的全部資源。
優點:簡單易實施且安全。
缺點:因爲某項資源不滿足,進程無法啓動,而其他已經滿足了的資源也不會得到利用,嚴重降低了資源的利用率,造成資源浪費。
使進程經常發生飢餓現象。
方法2:該方法是對第一種方法的改進,允許進程只獲得運行初期需要的資源,便開始運行,在運行過程中逐步釋放掉分配到的已經使用完畢的資源,然後再去請求新的資源。這樣的話,資源的利用率會得到提高,也會減少進程的飢餓問題。
b、破壞“不可搶佔”條件
當一個已經持有了一些資源的進程在提出新的資源請求沒有得到滿足時,它必須釋放已經保持的所有資源,待以後需要使用的時候再重新申請。這就意味着進程已佔有的資源會被短暫地釋放或者說是被搶佔了。
該種方法實現起來比較複雜,且代價也比較大。釋放已經保持的資源很有可能會導致進程之前的工作實效等,反覆的申請和釋放資源會導致進程的執行被無限的推遲,這不僅會延長進程的週轉週期,還會影響系統的吞吐量。
c、破壞“循環等待”條件
可以通過定義資源類型的線性順序來預防,可將每個資源編號,當一個進程佔有編號爲i的資源時,那麼它下一次申請資源只能申請編號大於i的資源。如圖所示:
這樣雖然避免了循環等待,但是這種方法是比較低效的,資源的執行速度回變慢,並且可能在沒有必要的情況下拒絕資源的訪問,比如說,進程c想要申請資源1,如果資源1並沒有被其他進程佔有,此時將它分配個進程c是沒有問題的,但是爲了避免產生循環等待,該申請會被拒絕,這樣就降低了資源的利用率 -
數據庫查詢時間(優化問題)
1、對查詢進行優化,應儘可能避免全表掃描
2、寫數據語句時儘可能減少表的全局掃描
3、不要在條件判斷時進行 算數運算
4、很多時候用 exists 代替 in 是一個好的選擇
淺談數據庫查詢優化的幾種思路 -
MySQL數據庫開發常見問題及幾點優化!
庫表設計
慢 SQL 問題
誤操作、程序 bug 時怎麼辦 -
字符串常量到底存在哪了?
1、局部變量存儲在棧中
2、全局變量、靜態變量(全局和局部靜態變量)存儲在靜態存儲區
3、new申請的內存是在堆中
4、字符串常量也是存儲在靜態存儲區 -
進程的通信? 管道、共享內存、信號量、消息隊列、SOCKET
Linux進程間通信:管道、信號、消息隊列、共享內存、信號量、套接字(socket)
Linux線程間通信:互斥量(mutex),信號量,條件變量
Windows進程間通信:管道、消息隊列、共享內存、信號量 (semaphore) 、套接字(socket)
Windows線程間通信:互斥量(mutex),信號量(semaphore)、臨界區(critical section)、事件(event)
Java進程間通信
傳統的進程間通信的方式有大致如下幾種:
(1) 管道(PIPE)
(2) 命名管道(FIFO)
(3) 信號量(Semphore)
(4) 消息隊列(MessageQueue)
(5) 共享內存(SharedMemory)
(6) Socket
Java如何支持進程間通信。
我們把Java進程理解爲JVM進程。很明顯,傳統的這些大部分技術是無法被我們的應用程序利用了(這些進程間通信都是靠系統調
用來實現的)。但是Java也有很多方法可以進行進程間通信的。 除了上面提到的Socket之外,當然首選的IPC可以使用RMI,另外Java nio的MappedByteBuffer也可以通過內存映射文件來實現進程間通信
17.二叉樹的前序遍歷和思路?
遞歸:
private void preorder(BinaryNode<T> p) { //根節點 if (p != null) { System.out.print(p.data.toString() + " ");//打印結點數值 preorder(p.left); //打印當前結點的左子樹 preorder(p.right); //打印當前結點的右子樹 } }
非遞歸
public void preorderTraverse() {
LinkedStack<BinaryNode<T>> stack = new LinkedStack<BinaryNode<T>>();
BinaryNode<T> p = this.root;
while (p != null || !stack.isEmpty()) {
if (p != null) {
System.out.print(p.data + " "); // 先根遍歷
stack.push(p);
p = p.left;
} else {
System.out.print("^ ");
p = stack.pop();
p = p.right;
}
}
}
-
計算機網絡中哪些協議用到了棧?
將所有的協議綜合起來,各個層次的所有協議被稱爲協議棧。因特網的協議棧由5個層次組成:物理層、鏈路層、網絡層、傳輸層和應用層。
HTTP網絡協議棧 -
圖的最短路徑的算法叫什麼?
Floyd(弗洛伊德)算法、迪傑斯特拉(Dijkstra)算法 -
鏈表有使用過嗎?講一下他的優點還有使用場景 //插入最快,查詢不快。
單向鏈表和雙向鏈表的優缺點及使用場景
Java集合List特點及使用場景分析 -
鏈表和樹的區別
鏈表和樹
樹是數據結構的一種邏輯結構形式,一個前驅,多個後繼
鏈表是數據結構的一種存儲結構形式,用數據域以外的附加存儲空間表明邏輯關係
樹存儲起來,可以用鏈式存儲實現 -
哈希結構和樹的區別
哈希表與紅黑樹的特點及區別
Java中HashMap和TreeMap的區別深入理解
b樹和b+樹的區別
B樹B-樹和B+樹的總結 -
輸入一個鏈表的頭結點,輸出當前節點距離最近的,比他大的下一個,要求用O(n)複雜度
找出數組中每個數右邊第一個比它大的元素–時間複雜度o(n)單調棧解法
聯想面試準備
- 後端應用(主要使用Python/Go/Java語言,框架涉及Django/Gin/Spring
Spring框架 - 熟悉Socket或網絡編程技術;熟悉多線程技術,進程間通訊技術;
- Java校招面試題目合集