StringBuilder和StringBuffer的區別:
String 字符串常量 不可變 使用字符串拼接時是不同的2個空間
StringBuffer 字符串變量 可變 線程安全 字符串拼接直接在字符串后追加
StringBuilder 字符串變量 可變 非線程安全 字符串拼接直接在字符串后追加
1.StringBuilder執行效率高於StringBuffer高於String.
2.String是一個常量,是不可變的,所以對於每一次+=賦值都會創建一個新的對象, StringBuffer和StringBuilder都是可變的,當進行字符串拼接時采用append方 法,在原來的基礎上進行追加,所以性能比String要高,又因為StringBuffer 是 線程安全的而StringBuilder是線程非安全的,所以StringBuilder的效率高於 StringBuffer.
3.對於大數據量的字符串的拼接,采用StringBuffer,StringBuilder.
Vector,ArrayList,LinkedList之間的區別:
一、同步性
ArrayList,LinkedList是不同步的,而Vestor是同步的。所以如果不要求線程安全的話,可以使用ArrayList或LinkedList,可以節省為同步而耗費的開銷。但在多線程的情況下,有時候就不得不使用Vector了。當然,也可以通過一些辦法包裝ArrayList,LinkedList,使他們也達到同步,但效率可能會有所降低。
二、數據增長
從內部實現機制來講ArrayList和Vector都是使用Objec的數組形式來存儲的。當你向這兩種類型中增加元素的時候,如果元素的數目超出了內部數組目前的長度它們都需要擴展內部數組的長度,Vector缺省情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最后你獲得的這個集合所占的空間總是比你實際需要的要大。所以如果你要在集合中保存大量的數據那么使用Vector有一些優勢,因為你可以通過設置集合的初始化大小來避免不必要的資源開銷。
三、檢索、插入、刪除對象的效率
ArrayList和Vector中,從指定的位置(用index)檢索一個對象,或在集合的末尾插入、刪除一個對象的時間是一樣的,可表示為O(1)。但是,如果在集合的其他位置增加或移除元素那么花費的時間會呈線形增長:O(n-i),其中n代表集合中元素的個數,i代表元素增加或移除元素的索引位置。為什么會這樣呢?以為在進行上述操作的時候集合中第i和第i個元素之后的所有元素都要執行(n-i)個對象的位移操作。
LinkedList中,在插入、刪除集合中任何位置的元素所花費的時間都是一樣的—O(1),但它在索引一個元素的時候比較慢,為O(i),其中i是索引的位置。
HashTable HashMap TreeMap之間的區別:
HashMap不是線程安全的,HashTable是線程安全。
HashMap允許空(null)的鍵和值(key),HashTable則不允許。
HashMap性能優於Hashtable。
TreeMap中所有的元素都保持着某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)
http報文包含哪些部分:
請求首行;
請求頭信息;
空行;
請求體;
post請求協議格式:
GET /Hello/index.jsp HTTP/1.1:GET請求,請求服務器路徑為Hello/index.jsp,協議為1.1;
Host:localhost:請求的主機名為localhost;
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0…:與瀏覽器和OS相關的信息。有些網站會顯示用戶的系統版本和瀏覽器版本信息,這都是通過獲取User-Agent頭信息而來的;
Accept: */*:告訴服務器,當前客戶端可以接收的文檔類型, */*,就表示什么都可以接收;
Accept-Language: zh-CN:當前客戶端支持的語言,可以在瀏覽器的工具à選項中找到語言相關信息;
Accept-Encoding: gzip, deflate:支持的壓縮格式。數據在網絡上傳遞時,服務器會把數據壓縮后再發送;
Connection: keep-alive:客戶端支持的鏈接方式,保持一段時間鏈接。
什么是Sql注入?如何防止sql注入?
所謂SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。具體來說,它是利用現有應用程序,將(惡意)的SQL命令注入到后台數據庫引擎執行的能力,它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。
怎么防止SQL注入,使用存儲過程來執行所有的查詢;檢查用戶輸入的合法性;將用戶的登錄名、密碼等數據加密保存。
Redirect和Forwod之間的區別?
1、從數據共享上
Forword是一個請求的延續,可以共享request的數據
Redirect開啟一個新的請求,不可以共享request的數據
2、從地址欄
Forword轉發地址欄不發生變化
Redirect轉發地址欄發生變化
談談線程同步,樂觀鎖,悲觀鎖的實現?
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。
兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下,即沖突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生沖突,上層應用會不斷的進行retry,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適。
實現過程
2.悲觀鎖:悲觀鎖的實現采用的數據庫內部的鎖機制,一個典型的倚賴數據庫的悲觀鎖調用:
select * from account where name=”張三” for update
這條sql 語句鎖定了account 表中所有符合檢索條件(name=”Erica”)的記錄。本次事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。也就是我們可以在查詢數據的時候先用for update把這條數據鎖住,然后更改完這條數據再提交。這樣別的線程沒法更新這條數據,也就保證了不會丟失更新。
2.1.悲觀鎖帶來的性能問題。我們試想一個場景:如一個金融系統,當某個操作員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶帳戶余額),如果采用悲觀鎖機制,也就意味着整個操作過程中(從操作員讀出數據、開始修改直至提交修改結果的全過程),數據庫記錄始終處於加鎖狀態,可以想見,如果面對幾百上千個並發,這樣的情況將導致怎樣的后果?所以我們這個時候可以使用樂觀鎖。
1.樂觀鎖:樂觀鎖的實現可以通過在表里面加一個版本號的形式,下面是一個實例。
講解:也就是每個人更新的時候都會判斷當前的版本號是否跟我查詢出來得到的版本號是否一致,不一致就更新失敗,一致就更新這條記錄並更改版本號。
Sql查詢語句的優化?DB索引使用場景?
1、在表中建立索引,優先考慮where、group by使用到的字段。
2、盡量避免使用select *,返回無用的字段會降低查詢效率。如下:
SELECT * FROM t
優化方式:使用具體的字段代替*,只返回使用到的字段。
3、盡量避免使用in 和not in,會導致數據庫引擎放棄索引進行全表掃描。如下:
SELECT * FROM t WHERE id IN (2,3)
SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)
優化方式:如果是連續數值,可以用between代替。如下:
SELECT * FROM t WHERE id BETWEEN 2 AND 3
如果是子查詢,可以用exists代替。如下:
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)
4、盡量避免使用or,會導致數據庫引擎放棄索引進行全表掃描。如下:
SELECT * FROM t WHERE id = 1 OR id = 3
優化方式:可以用union代替or。如下:
SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 3
(PS:如果or兩邊的字段是同一個,如例子中這樣。貌似兩種方式效率差不多,即使union掃描的是索引,or掃描的是全表)
5、盡量避免在字段開頭模糊查詢,會導致數據庫引擎放棄索引進行全表掃描。如下:
SELECT * FROM t WHERE username LIKE '%li%'
優化方式:盡量在字段后面使用模糊查詢。如下:
SELECT * FROM t WHERE username LIKE 'li%'
6、盡量避免進行null值的判斷,會導致數據庫引擎放棄索引進行全表掃描。如下:
SELECT * FROM t WHERE score IS NULL
優化方式:可以給字段添加默認值0,對0值進行判斷。如下:
SELECT * FROM t WHERE score = 0
7、盡量避免在where條件中等號的左側進行表達式、函數操作,會導致數據庫引擎放棄索引進行全表掃描。如下:
SELECT * FROM t2 WHERE score/10 = 9
SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'
優化方式:可以將表達式、函數操作移動到等號右側。如下:
SELECT * FROM t2 WHERE score = 10*9
SELECT * FROM t2 WHERE username LIKE 'li%'
8、當數據量大時,避免使用where 1=1的條件。通常為了方便拼裝查詢條件,我們會默認使用該條件,數據庫引擎會放棄索引進行全表掃描。如下:
SELECT * FROM t WHERE 1=1
優化方式:用代碼拼裝sql時進行判斷,沒where加where,有where加and。
Spring在項目中怎么用 ioc Aop實現原理 功能 使用場景?
ioc依賴注入的思想是通過反射機制實現的,在實例化一個類時,它通過反射調用類中set方法將事先保存在HashMap中的類屬性注入到類中。 總而言之,在傳統的對象創建方式中,通常由調用者來創建被調用者的實例,而在Spring中創建被調用者的工作由Spring來完成,然后注入調用者,即所謂的依賴注入or控制反轉。 注入方式有兩種:依賴注入和設置注入; IoC的優點:降低了組件之間的耦合,降低了業務對象之間替換的復雜性,使之能夠靈活的管理對象。
AOP利用一種稱為“橫切”的技術,剖解開封裝的對象內部,並將那些影響了 多個類的公共行為封裝到一個可重用模塊,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模塊所共同調用的 邏輯或責任封裝起來,比如日志記錄,便於減少系統的重復代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。
實現AOP的技術,主要分為兩大類:一是采用動態代理技術,利用截取消息的方式,對該消息進行裝飾,以取代原有對象行為的執行;二是采用靜態織入的方式,引入特定的語法創建“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的代碼。
AOP使用場景:
Authentication 權限檢查
Caching 緩存
Context passing 內容傳遞
Error handling 錯誤處理
Lazy loading 延遲加載
Debugging 調試
logging, tracing, profiling and monitoring 日志記錄,跟蹤,優化,校准
Performance optimization 性能優化,效率檢查
Persistence 持久化
Resource pooling 資源池
Synchronization 同步
Transactions 事務管理
異步編程的理解 :
異步編程提供了一個非阻塞的,事件驅動的編程模型。 這種編程模型利用系統中多核執行任務來提供並行,因此提供了應用的吞吐率。此處吞吐率是指在單位時間內所做任務的數量。 在這種編程方式下, 一個工作單元將獨立於主應用線程而執行, 並且會將它的狀態通知調用線程:成功,處理中或者失敗。
我們需要異步來消除阻塞模型。其實異步編程模型可以使用同樣的線程來處理多個請求, 這些請求不會阻塞這個線程。想象一個應用正在使用的線程正在執行任務, 然后等待任務完成才進行下一步。 log框架就是一個很好的例子:典型地你想將異常和錯誤日志記錄到一個目標中, 比如文件,數據庫或者其它類似地方。你不會讓你的程序等待日志寫完才執行,否則程序的響應就會受到影響。 相反,如果對log框架的調用是異步地,應用就可以並發執行其它任務而無需等待。這是一個非阻塞執行的例子。
為了在Java中實現異步,你需要使用Future
和 FutureTask
, 它們位於java.util.concurrent
包下. Future
是一個接口而FutureTask
是它的一個實現類。實際上,如果在你的代碼中使用Future
, 你的異步任務會立即執行, 並且調用線程可以得到結果promise
。
下面的代碼片段定義了一個包含兩個方法的接口。 一個是同步方法,另外一個是異步方法。
import java.util.concurrent.Future; public interface IDataManager { // synchronous method public String getDataSynchronously(); // asynchronous method public Future<String> getDataAsynchronously(); }
值得注意的是回調模型的弊端就是當回調嵌套時很麻煩。