Java面試題-阿里、餓了麼、鏈家、攜程

阿里內推:https://blog.csdn.net/hehuanchun0311/article/details/105775657

一、J2SE部分

1、Java基礎


==與equals()方法的區別?

1. ==在比較基本數據類型時比較的是值,比較兩個對象時比較的是地址值;
2. equals()方法存在於Object類中,Object類中equals()方法底層依賴的是==操作,
   在所有沒有重寫equals()的類中,調用equals()其實和使用==的效果一樣,也是比較的地址值。
   String重寫了equals(),底層比較的是兩個String對應位置的char字符是否==。

爲什麼重寫equals()方法就必須重寫hashCode()方法?

1. Object.hashCode()方法是一個本地native方法,返回的是對象引用中存儲的對象的內存地址;
2. 基於散列的集合(HashSet、HashMap和Hashtable)存放key時,調用該對象(存入對象)的hashCode()方法來得到該對象的hashCode值,然後根據該hashCode值決定該對象在HashSet中存儲的位置;
3. 所以如果equals方法返回true,那麼兩個對象的hasCode()返回值必須一樣;

Object有哪些方法?

1. equals()、hashCode()、getClass()、toString()--默認字符串:類名+哈希編碼;
2. clone():實現對象的淺複製(當改變其中一個對象的引用類型屬性實例的屬性時,另一個對象相應的引用類型的屬性實例中的屬性也會發生變化),只有實現了Cloneable接口纔可以調用該方法。否則拋出CloneNotSupportedException;深複製:引用類型屬性也要實現clone()方法並顯式調用;
3. finalize():用於JVM對象收集;
4. wait():使當前線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是具有該對象的鎖。wait()方法一直等待,直到獲得鎖或者被中斷;
5. notify():喚醒在該對象上等待的某個線程;
6. notifyAll():喚醒在該對象上等待的所有線程;

接口和抽象類的區別,什麼情況下用接口或抽象類?

區別:接口裏面方法都是沒有實現的,抽象類裏面可以有部分是實現的方法。
抽象類:只有一個或幾個方法需要定義成抽象方法,從而讓子類來實現;其他方法具有清晰、明確、共同的邏輯需要在本類中實現,由子類“共享”和“複用”。
接口:純粹定義方法接口,所有方法都由實現該接口的類來實現。沒有共享的公共邏輯,此時用接口比較合適。

String、StringBuffer、StringBuilder區別

不可變:String,底層是final char value[]
可變:StringBuffer、StringBuilder,底層是char[] value
線程安全:StringBuffer
線程不安全:StringBuilder

爲什麼String設計成不可變?

1. 字符串常量池的需要:字符串常量池是Java堆內存中一個特殊的存儲區域, 當創建一個String對象時,假如此字符串值已經存在於常量池中,則不會創建一個新的對象,而是引用已經存在的對象;
2. 允許String對象緩存HashCode:Java中String對象的哈希碼被頻繁地使用,字符串不變性保證了hash碼的唯一性,因此可以放心地進行緩存。這也是一種性能優化手段,意味着不必每次都去計算新的哈希碼;
3. 安全性:String常被用來當做參數,例如 網絡連接地址URL,文件路徑path,還有反射機制所需要的String參數等, 假若String不是固定不變的,將會引起各種安全隱患。

序列化和反序列化?

概念:
1. 把對象轉換爲字節序列的過程稱爲對象的序列化;
2. 把字節序列恢復爲對象的過程稱爲對象的反序列化。
用途:
1. 把對象的字節序列永久地保存到硬盤上,讓它們離開內存空間,入住物理硬盤,等要用了,再把保存在硬盤中的對象還原到內存中;
2. 在網絡上傳送對象的字節序列;
實現:
1. ObjectOutputStream代表對象輸出流,它的writeObject(Object obj)方法可對參數指定的obj對象進行序列化,把得到的字節序列寫到一個目標輸出流中;
2. ObjectInputStream代表對象輸入流,它的readObject()方法從一個源輸入流中讀取字節序列,再把它們反序列化爲一個對象,並將其返回;
3. 只有實現了Serializable接口的類的對象才能被序列化;
serialVersionUID的作用:
1. 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;
2. 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。

SpringBoot優缺點?

優點:快速構建項目、對主流開發框架的無配置集成(約定優於配置)、項目可獨立運行,無須外部依賴Servlet容器(內置tomcat插件)、Spring Maven版本統一管理(避免版本衝突);
缺點:集成度較高,使用過程中不太容易瞭解底層,部署出現問題難以排查;

爲什麼要用註冊中心?

1. 服務註冊後,及時發現;
2. 服務宕機後,及時下線;
3. 服務發現時,進行路由;

2、集合


list和set的區別,linklist和arraylist的區別和應用場景;

list:有序、可重複、可插入null
set:無序、不可重複、只能插入一個null值
linklist:鏈表實現,方便插入和刪除
arraylist:數組實現,方便隨機訪問

Arraylist、HashMap的初始容量、加載因子、擴容增量?

ArrayList::10、1、原容量的0.5倍
HashMap:16、0.75、原容量的1倍

有序的Map有哪些?爲什麼TreeMap是有序的?哪些集合是線程安全的?

有序Map: LinkedHashMap(按插入順序)、TreeMap(默認是按key的升序排序,也可以重寫Comparator方法自定義排序)
TreeMap有序原因:實現了SortedMap接口
線程安全的集合:Vector、Hashtable、ConcurrentHashMap

HashMap的底層數據結構,是如何插入的?哈希衝突解決方案?

底層:HashMap底層實現還是數組,只是數組的一個元素可能是一個單鏈表(哈希衝突時纔是鏈表)。
插入:put過程是先計算hash然後通過hash與table.length取摸計算index值,然後將key放到table[index]位置,當table[index]已存在其它元素時(哈希衝突),會在table[index]位置形成一個鏈表,將新添加的元素放在table[index],原來的元素通過Entry的next進行鏈接(新值鏈頭,原值後移)--哈希衝突的解決方案;
獲取:先根據key的hash值得到這個元素在數組中的位置,然後通過key的equals()在鏈表中找到key對應的Entry節點;

HashMap和Hashtable的區別?

區別:
a. 主要的區別在於Hashtable是線程安全,而HashMap則非線程安全;Hashtable的實現方法裏面都添加了synchronized關鍵字來確保線程同步,若無特殊需求建議使用HashMap,在多線程環境下若使用HashMap需要使用Collections.synchronizedMap()方法來獲取一個線程安全的集合;
注:HashSet內部使用HashMap,把存儲的值作爲 key。

ConcurrentHashMap實現?JDK1.8之後優化?

要實現線程安全,就需要加鎖, HashTable就是線程安全的, 但是HashTable對整張表加鎖的做法非常消耗性能, ConcurrentMap的做法簡單來說, 就是把哈希表分成若干段, 對其中某一段操作時, 只鎖住這一段, 其他段可以不受影響。
實現:
a. 整個ConcurrentMap由一個segment數組組成(即segments),數組中每一個segment是一張哈希表, 哈希表中存放的是一張hashentry鏈表。Segment繼承ReentrantLock用來充當鎖的角色。
b. 最終存儲key,value時是對segment操作, 因此只要對需要插入鍵值對的segment上鎖就可以保證線程安全。
JDK1.8之後的優化:
1. 取消segment字段,直接採用transient volatile HashEntry<K,V> table保存數據,採用table數組元素作爲鎖,從而實現了對每一行數據進行加鎖,進一步減少併發衝突的概率;transient修飾的變量其內容在序列化後無法獲得訪問;
2. 將原先table數組+單向鏈表的數據結構,變更爲table數組+單向鏈表+紅黑樹的結構;

3、線程


進程和線程的區別?

(1)進程是資源的分配和調度的一個獨立單元,而線程是CPU調度的基本單元;
(2)同一個進程中可以包括多個線程,並且線程共享整個進程的資源;
(3)線程中執行時一般都要進行同步和互斥,因爲他們共享同一進程的所有資源;

線程安全與非線程安全?

線程安全就是多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,其他線程不能進行訪問直到該線程讀取完,其他線程纔可使用。不會出現數據不一致或者數據污染;
線程不安全就是不提供數據訪問保護,有可能出現多個線程先後更改數據造成所得到的數據是髒數據;

線程的生命週期

新建(new Thread):當創建Thread類的一個實例(對象)時,此線程進入新建狀態(未被啓動)。t = new Thread();
就緒(runnable):線程已經被啓動,正在等待被分配給CPU時間片,也就是說此時線程正在就緒隊列中排隊等候得到CPU資源。t.start();
運行(running):線程獲得CPU資源正在執行任務(run()方法);
死亡(dead):當線程執行完畢、發生異常或被其它線程殺死,線程就進入死亡狀態,這時線程不可能再進入就緒狀態等待執行。
堵塞(blocked):由於某種原因導致正在運行的線程讓出CPU並暫停自己的執行,即進入堵塞狀態。用sleep(long t) 方法可使線程進入睡眠方式。一個睡眠着的線程在指定的時間過去可進入就緒狀態。

多線程的實現方式,start()是立刻啓動嗎?

實現:繼承Thread類、實現Runnable接口、線程池(Cache、Fixed、Single、Schedule)、實現Callable接口通過FutureTask包裝器來創建Thread線程;
不是立刻啓動:執行start()之後,線程等待CPU調度,當調度成功時,調用run()才啓動線程;

volatile和synchronized的區別?

>volatile關鍵字的作用是:使變量在多個線程間可見(可見性)
a. 強制變量每次從內存中讀取,而不會存儲在寄存器中(強制刷新到內存中);synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住;
b. volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的;
c. volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞;

Lock和synchronized區別?

a. Lock是一個接口,而synchronized是java的一個關鍵字
b. synchronized在發生異常時候會自動釋放佔有的鎖,因此不會出現死鎖;而lock發生異常時候,不會主動釋放佔有的鎖,必須手動unlock來釋放鎖,可能引起死鎖的發生。synchronized同步的代碼塊執行結束後鎖可以由JVM自動釋放,Lock不行。
c. Lock可以通過trylock來知道有沒有獲取鎖,而synchronized不能;
d. Lock可實現讀寫分離,ReentrantReadWriteLock;

wait()和notify()

a. wait()使線程停止運行;
b. notify()使停止的線程繼續運行;
c. wait(long)等待long時間,如果沒有喚醒,自動甦醒;

sleep() 和 wait() 區別?

wait()是Object類的方法,sleep()和yield()是Thread類的靜態方法。sleep和yield方法是用來讓線程讓出CPU時間,把CPU交給線程調度器,使得其他線程能獲得CPU時間。sleep()睡眠時,保持對象鎖;而wait()睡眠時,釋放對象鎖。

什麼是阻塞?阻塞的情況?

阻塞狀態是指線程因爲某種原因放棄了cpu使用權,也即讓出了cpu時間片,暫時停止運行。直到線程進入可運行(runnable)狀態,纔有機會再次獲得cpu時間片轉到運行(running)狀態。
a. 等待阻塞:運行(running)的線程執行o.wait()方法,JVM會把該線程放入等待隊列(waitting queue)中。
b. 同步阻塞:運行(running)的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池(lock pool)中。
c. 其他阻塞:運行(running)的線程執行Thread.sleep(long ms),JVM會把該線程置爲阻塞狀態。當sleep()狀態超時,線程重新轉入可運行(runnable)狀態。)

Semaphore和LockSupport的作用?

Semaphore:計數信號量。Semaphore管理一系列許可證。它的每個acquire方法阻塞,直到有一個許可證可以獲得然後拿走一個許可證;每個release方法增加一個許可證。經常用於限制獲取某種資源的線程數量。
LockSupport:它的park()和unPark()對應Object的wait()和notify()。

CAS

Compare And Set的簡稱。現代主流CPU都支持的一種硬件級別的原子操作, 比較並交換, 操作包含三個操作數:內存地址(V) 預期原值(A) 新值(B)
如果內存位置的值與預期原值相匹配, 那麼處理器會自動將該位置值更新爲新值,否則, 處理器不做任何操作.無論哪種情況, 它都會在CAS指令之前返回該位置的值.

ReentrantLock的實現

基於AQS:volatile int state;
獲取鎖:嘗試對state進行CAS(0,1)操作,嘗試幾次失敗後就掛起線程,進入等待隊列。
釋放鎖:對state進行CAS(1,0)操作,然後去喚醒等待隊列中的一個線程。
//默認創建非公平鎖
public ReentrantLock() {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

ThreadPoolExecutor的重要參數?執行順序?

corePoolSize:核心線程數
1. 核心線程會一直存活,及時沒有任務需要執行;
2. 當線程數小於核心線程數時,即使有線程空閒,線程池也會優先創建新線程處理;
3. 設置allowCoreThreadTimeout=true(默認false)時,核心線程會超時關閉;
queueCapacity:任務隊列容量(阻塞隊列)
1. 當核心線程數達到最大時,新任務會放在隊列中排隊等待執行
maxPoolSize:最大線程數
keepAliveTime:線程空閒時間
1. 當線程空閒時間達到keepAliveTime時,線程會退出,直到線程數量=corePoolSize;
2. 如果allowCoreThreadTimeout=true,則會直到線程數量=0;
allowCoreThreadTimeout:允許核心線程超時
ThreadPoolExecutor執行順序:
1. 當線程數小於核心線程數時,創建線程。
2. 當線程數大於等於核心線程數,且任務隊列未滿時,將任務放入任務隊列。
3. 當線程數大於等於核心線程數,且任務隊列已滿
	 若線程數小於最大線程數,創建線程;
	 若線程數等於最大線程數,拋出異常,拒絕任務;

4、JVM


JVM參數

堆大小:-Xms3550m, 初始化堆大小;-Xmx3550m,最大堆大小。堆 = 年輕代 + 年老代+ 持久代
永久代:-XX:Permsize=512m,設置永久代初始值;-XX:MaxPermsize=512m,設置永久代的最大值。 
收集器:-XX:MaxGCPauseMillis=10,設置垃圾收集停頓的最大毫秒數;

OOM解決方案

OOM for Perm:增加永久保存區域(這塊內存主要是被JVM存放Class和Meta信息的)大小:-XX:MaxPermSize(默認64M)
OOM for GC:對象過多,導致內存溢出-->調整GC的策略,比如老生代存活率設置爲80%;

垃圾收集算法

a. 標記-清除:標記需要回收的對象;清除被標記的對象;
b. 複製:內存分爲兩塊,每次只用一塊;當這一塊使用完後,將還存活的對象放到另一塊中去;未複製對象清除;
c. 標記-整理:標記需要回收的對象;讓所有可用的對象都向一端移動;然後直接清理掉端邊界的對象內存;
d. 分代收集:新生代(新生成的對象,採用複製算法)+ 老年代(經歷了N次垃圾回收後仍然存活的對象,採用標記-清除或標記-整理算法);

標記:

引用計數:引用一次+1,引用失敗-1,引用計數器爲0即被標記;

可達性分析:通過一系列稱爲"GC Root"的對象作爲起始點,向下搜索行程引用鏈,不在引用鏈中即爲被標記;

5、數據庫


數據庫查詢緩慢是什麼原因,如何優化?

原因:執行復雜的邏輯或統計、全表掃描、索引失效、join的表過多等;
索引失效優化:
a. where 子句中使用!=或<>操作符、函數操作、表達式(如:num/2)以及null值判斷;
b. in 、 not in 、or 也要慎用,否則條件超過一定數量會導致索引失效;
c. 模糊查詢(LIKE)時避免在關鍵詞前使用”%”(如:LIKE '%小分期');
其他優化:
a. JOIN時使用小結果集驅動大結果集;
b. JOIN時條件判斷應放在on中,避免在後面加where;

數據庫事務的用途,如何開啓?

try {//設置禁止自動提交事務
    connection.setAutoCommit( false);
    通過conn得到stmt進行數據庫操作...
    connection.commit(); //統一提交
} catch(Exception ex) {
    connection.rollback();
} finally {
    connection和statement的關閉
}

數據庫的樂觀鎖和悲觀鎖?

樂觀鎖:樂觀鎖是指操作數據庫時(更新操作),想法很樂觀,認爲這次的操作不會導致衝突,在操作數據時,並不進行任何其他的特殊處理(也就是不加鎖),而在進行更新後,再去判斷是否有衝突了。
實現:樂觀鎖不是數據庫自帶的,需要我們自己去實現。比如更新記錄時檢查當前記錄version字段值是否與數據庫中記錄當前version一致。
悲觀鎖:悲觀鎖就是在操作數據時,認爲此操作會出現數據衝突,所以在進行每次操作時都要通過獲取鎖才能進行對相同數據的操作。
實現:悲觀鎖是由數據庫自己實現了的,使用Repeatable Read的隔離級別,然後執行相應的SQL語句即可。

MySQL的共享鎖和排他鎖?

共享鎖:共享鎖又稱讀鎖,是讀取操作創建的鎖。如果事務T對數據A加上共享鎖後,則其他事務只能對A再加共享鎖,不能加排他鎖。獲准共享鎖的事務只能讀數據,不能修改數據。
使用:SELECT ... LOCK IN SHARE MODE;
排他鎖:排他鎖又稱寫鎖,如果事務T對數據A加上排他鎖後,則其他事務不能再對A加任任何類型的封鎖。獲准排他鎖的事務既能讀數據,又能修改數據。
使用:SELECT ... FOR UPDATE;

數據庫事務的特性(ACID)和隔離級別?

ACID:
1)原子性: 原子性是指事務是一個不可再分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2)一致性:數據庫事務不能破壞關係數據的完整性以及業務邏輯上的一致性。
3)隔離性:隔離性是指併發的事務是相互隔離的。
4)持久性:持久性是指在事務完成以後,該事務所對數據庫所作的更改便持久的保存在數據庫之中,並不會被回滾。即使出現了任何事故比如斷電等,事務一旦提交,則持久化保存在數據庫中。
隔離級別:
a. Read uncommitted:讀未提交,一個事務可以讀取另一個未提交事務的數據。引發髒讀;
b. Read committed:讀提交,一個事務要等另一個事務提交後才能讀取數據。引發不可重複讀(UPDATE操作:A準備用卡買單時,B正使用該卡全額付款並提交後,A再買單時發現餘額不足);
c. Repeatable read:重複讀,就是在開始讀取數據(事務開啓)時,不再允許修改操作。引發幻讀(INSERT操作:程序員某一天去消費,花了2千元,然後他的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啓),看到確實是花了2千元,就在這個時候,程序員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子打印程序員的消費記錄清單時(妻子事務提交),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀);
d. Serializable:事務串行化順序執行,可以避免髒讀、不可重複讀與幻讀。但是這種事務隔離級別效率低下,比較耗數據庫性能,一般不使用;
// Oracel、Sql Server默認Read committed,Mysql默認Repeatable read;

MySQL分佈式事務?

InnoDB存儲引擎提供了對XA事務的支持,並通過XA事務來支持分佈式事務的實現。分佈式事務指的是允許多個獨立的事務資源參與到一個全局的事務中。事務資源通常是關係型數據庫系統,但也可以是其他類型的資源。在使用分佈式事務時,InnoDB存儲引擎的事務隔離級別必須設置爲Serializable。

什麼是死鎖,死鎖的四個必要條件?

死鎖:是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象(雙方都掌握有對方所要的資源);
必要條件:
a. 互斥條件:資源是獨佔的且排他使用;
b. 不可剝奪條件:進程所獲得的資源在未使用完畢之前,不被其他進程強行剝奪;
c. 請求和保持條件:進程每次申請它所需要的一部分資源,在申請新的資源的同時,繼續佔用已分配到的資源;
d. 循環等待條件:在發生死鎖時必然存在一個進程等待隊列{P1,P2,…,Pn},其中P1等待P2佔有的資源,P2等待P3佔有的資源,…,Pn等待P1佔有的資源,形成一個進程等待環路;

如何處理死鎖?

預防死鎖:

a. 資源一次性分配:(破壞請求和保持條件)
b. 可剝奪資源:即當某進程新的資源未滿足時,釋放已佔有的資源(破壞不可剝奪條件)
c. 資源有序分配法:系統給每類資源賦予一個編號,每一個進程按編號遞增的順序請求資源,釋放則相反(破壞環路等待條件)

避免死鎖:

預防死鎖的幾種策略,會嚴重地損害系統性能。因此在避免死鎖時,要施加較弱的限制,從而獲得較滿意的系統性能。由於在避免死鎖的策略中,允許進程動態地申請資源。因而,系統在進行資源分配之前預先計算資源分配的安全性。若此次分配不會導致系統進入不安全狀態,則將資源分配給進程;否則,進程等待。其中最具有代表性的避免死鎖算法是銀行家算法。

緩存穿透和緩存雪崩?

緩存穿透含義:一般的緩存系統,都是按照key去緩存查詢,如果不存在對應的value,就去DB查找。如果key對應的value是一定不存在的,並且對該key併發請求量很大,就會對DB造成很大的壓力。這就叫做緩存穿透。
緩存穿透解決方案:
1. 對查詢結果爲空的情況也進行緩存,緩存時間設置短一點,或者該key對應的數據insert了之後清理緩存;
2. 對一定不存在的key進行過濾。可以把所有的可能存在的key放到一個大的set中,查詢時通過該set過濾(用的較少);
緩存雪崩含義:當緩存服務器重啓或者大量緩存集中在某一個時間段失效,這樣在失效的時候,也會給DB帶來很大壓力;
緩存雪崩解決方案:
1. 在緩存失效後,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待;
2. 不同的key,設置不同的過期時間,讓緩存失效的時間點儘量均勻;
3. 做二級緩存,A1爲原始緩存,A2爲拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置爲短期,A2設置爲長期;

二、計算機基礎部分

TCP的三次握手和四次揮手,瀏覽器訪問一個網址的過程?

位碼即tcp標誌位,有6種表示:SYN(synchronous建立連接)、ACK(acknowledgement 表示響應、確認)、PSH(push表示有DATA數據傳輸)、FIN(finish關閉連接)、RST(reset表示連接重置)、URG(urgent緊急指針字段值有效)
三次握手(建立連接):
第一次握手:客戶端發送syn包(syn=x)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
四次揮手(斷開連接):
第一次揮手:主動關閉方發送一個FIN,用來關閉主動方到被動關閉方的數據傳送。也就是主動關閉方告訴被動關閉方:我已經不會再給你發數據了。
第二次揮手:被動關閉方收到FIN包後,發送一個ACK給對方,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號)。
第三次揮手:被動關閉方發送一個FIN,用來關閉被動關閉方到主動關閉方的數據傳送,也就是告訴主動關閉方,我的數據也發送完了,不會再給你發數據了。
第四次揮手:主動關閉方收到FIN後,發送一個ACK給被動關閉方,確認序號爲收到序號+1,至此,完成四次揮手。
訪問過程:域名解析-->三次握手-->傳輸數據-->四次揮手

TCP與UDP區別?

1. TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接;
2. TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付;
3. 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信;
4. UDP具有較好的實時性,工作效率比TCP高,適用於對高速傳輸和實時性有較高的通信或廣播通信;

linux中文件權限

rwxr-xr-x(或755):包括屬主、屬組、其他
chomd 文件名 權限

HTTP、HTTPS區別?

a. HTTP協議傳輸的數據都是未加密的,也就是明文的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸
b. https協議需要到ca申請證書;

三、數據結構部分

常用排序思想

插入排序

每步將一個待排序的記錄,按其順序碼大小插入到前面已經排序的字序列的合適位置,直到全部插入排序完爲止。

直接插入排序:每步將一個待排序的記錄,按其順序碼大小插入到前面已經排序的字序列的合適位置(從後向前找到合適位置後),直到全部插入排序完爲止。
二分法插入排序:二分法插入排序的思想和直接插入一樣,只是找合適的插入位置的方式不同,這裏是按二分法找到合適的位置,可以減少比較的次數。
希爾排序:先取一個小於n的整數d1作爲第一個增量,把文件的全部記錄分成d1個組。所有距離爲d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2。

選擇排序

每趟從待排序的記錄序列中選擇關鍵字最小的記錄放置到已排序表的最前位置,直到全部排完。

直接選擇排序:在要排序的一組數中,選出最小的一個數與第一個位置的數交換;然後在剩下的數當中再找最小的與第二個位置的數交換,如此循環到倒數第二個數和最後一個數比較爲止。
堆排序:

交換排序

冒泡排序:在要排序的一組數中,對當前還未排好序的範圍內的全部數,自上而下對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒。即:每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就將它們互換。
快速排序:選擇一個基準元素,通常選擇第一個元素或者最後一個元素,通過一趟掃描,將待排序列分成兩部分,一部分比基準元素小,一部分大於等於基準元素,此時基準元素在其排好序後的正確位置,然後再用同樣的方法遞歸地排序劃分的兩部分。

歸併排序

歸併(Merge)排序法是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分爲若干個子序列,每個子序列是有序的。然後再把有序子序列合併爲整體有序序列。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章