Java中抽象類(lèi)和接口類(lèi)
在抽象類(lèi)中的方法不一定是抽象方法揪胃,含有抽象方法的類(lèi)必須定義成抽象類(lèi)修械。
什么時(shí)候使用抽象類(lèi)和接口
如果你擁有一些方法并且想讓它們中的一些有默認(rèn)實(shí)現(xiàn),那么使用抽象類(lèi)吧。
如果你想實(shí)現(xiàn)多重繼承友题,那么你必須使用接口功蜓。由于Java不支持多繼承园爷,子類(lèi)不能夠繼承多個(gè)類(lèi),但可以實(shí)現(xiàn)多個(gè)接口霞赫。因此你就可以使用接口來(lái)解決它腮介。
如果基本功能在不斷改變,那么就需要使用抽象類(lèi)端衰。如果不斷改變基本功能并且使用接口叠洗,那么就需要改變所有實(shí)現(xiàn)了該接口的類(lèi)。
抽象類(lèi)的定義
public abstract class Base{
? ? abstract void hello();
}
Method invoke()的使用
invoke方法用來(lái)反射其他類(lèi)的方法.比如將方法當(dāng)作參數(shù)傳入函數(shù)中
如何使用
1.? 需要傳入的類(lèi).class.getMethod(方法名,和方法參數(shù));
如果方法參數(shù)是數(shù)組類(lèi)型 如int[],則寫(xiě)int[].class
PS:
getDeclaredMethod*獲取的是類(lèi)自身聲明的所有方法旅东,包含public灭抑、protected和private方法
getMethod*獲取的是類(lèi)的所有共有方法,這就包括自身的所有public方法抵代,和從基類(lèi)繼承的腾节、從接口實(shí)現(xiàn)的所有public方法。
2.
method.invoke()有兩個(gè)參數(shù),如果你需要調(diào)用的函數(shù)非靜態(tài)的,則為他創(chuàng)建一個(gè)實(shí)例作為第一個(gè)參數(shù),如過(guò)是靜態(tài)函數(shù)則為null.? ?第二參數(shù)為被調(diào)用函數(shù)的參數(shù),注意需要Object封裝 如new Object[]{arr}.
Java實(shí)現(xiàn)線程的兩種方式
1.繼承Thread,重寫(xiě)run()方法
2.實(shí)現(xiàn)Runable接口,再通過(guò)Thread構(gòu)造函數(shù)實(shí)例化
線程安全
線程安全概念:當(dāng)多個(gè)線程訪問(wèn)某一個(gè)類(lèi)(對(duì)象或方法)時(shí)案腺,這個(gè)類(lèi)始終能表現(xiàn)出正確的行為庆冕,那么這個(gè)類(lèi)(對(duì)象或方法)就是線程安全的。
線程安全就是多線程訪問(wèn)時(shí)劈榨,采用了加鎖機(jī)制访递,當(dāng)一個(gè)線程訪問(wèn)該類(lèi)的某個(gè)數(shù)據(jù)時(shí),進(jìn)行保護(hù)同辣,其他線程不能進(jìn)行訪問(wèn)直到該線程讀取完拷姿,其他線程才可使用。不會(huì)出現(xiàn)數(shù)據(jù)不一致或者數(shù)據(jù)污染旱函。 線程不安全就是不提供數(shù)據(jù)訪問(wèn)保護(hù)响巢,有可能出現(xiàn)多個(gè)線程先后更改數(shù)據(jù)造成所得到的數(shù)據(jù)是臟數(shù)據(jù)。這里的加鎖機(jī)制常見(jiàn)的如:synchronized
synchronized:可以在任意對(duì)象及方法上加鎖棒妨,而加鎖的這段代碼稱為“互斥區(qū)”或“臨界區(qū)”踪古。
什么是java序列化,如何實(shí)現(xiàn)java序列化
將對(duì)象以流的方式保存在磁盤(pán)中靶衍,實(shí)現(xiàn)序列化接口? 序列化:把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的方法灾炭。?? 反序列化:把字節(jié)序列恢復(fù)到Java對(duì)象的過(guò)程。
工廠模式生產(chǎn)者颅眶、消費(fèi)者模式?單例模式
請(qǐng)論述vector和ArrayList的區(qū)別Vector:
arrayList是非線程安全蜈出,vector是線程安全
當(dāng)Vector或ArrayList中的元素超過(guò)它的初始大小時(shí),Vector會(huì)將它的容量翻倍,而ArrayList只增加50%的大小,這樣,ArrayList就有利于節(jié)約內(nèi)存空間涛酗。
#{}和${}的區(qū)別是什么铡原?
#{}是預(yù)編譯處理,${}是字符串替換商叹。
Mybatis在處理#{}時(shí)燕刻,會(huì)將sql中的#{}替換為?號(hào),調(diào)用PreparedStatement的set方法來(lái)賦值剖笙;
Mybatis在處理${}時(shí)卵洗,就是把${}替換成變量的值。
使用#{}可以有效的防止SQL注入弥咪,提高系統(tǒng)安全性过蹂。
Mybatis是如何進(jìn)行分頁(yè)的?分頁(yè)插件的原理是什么聚至?
Mybatis使用RowBounds對(duì)象進(jìn)行分頁(yè)酷勺,它是針對(duì)ResultSet結(jié)果集執(zhí)行的內(nèi)存分頁(yè),而非物理分頁(yè)扳躬,可以在sql內(nèi)直接書(shū)寫(xiě)帶有物理分頁(yè)的參數(shù)來(lái)完成物理分頁(yè)功能脆诉,也可以使用分頁(yè)插件來(lái)完成物理分頁(yè)甚亭。
分頁(yè)插件的基本原理是使用Mybatis提供的插件接口,實(shí)現(xiàn)自定義插件击胜,在插件的攔截方法內(nèi)攔截待執(zhí)行的sql亏狰,然后重寫(xiě)sql,根據(jù)dialect方言潜的,添加對(duì)應(yīng)的物理分頁(yè)語(yǔ)句和物理分頁(yè)參數(shù)骚揍。
啟動(dòng)nginx ?./sbin/nginx?
停止nginx ./sbin/nginx -s stop ? ?./sbin/nginx -s quit
正向代理反向代理
https://www.cnblogs.com/Anker/p/6056540.html
nginx功能
作為http server(代替apache,對(duì)PHP需要FastCGI處理器支持)
反向代理服務(wù)器
實(shí)現(xiàn)負(fù)載均衡
虛擬主機(jī)
FastCGI:Nginx本身不支持PHP等語(yǔ)言啰挪,但是它可以通過(guò)FastCGI來(lái)將請(qǐng)求扔給某些語(yǔ)言或框架處理
nginx和apache的區(qū)別
輕量級(jí),同樣起web 服務(wù)嘲叔,比apache 占用更少的內(nèi)存及資源?
抗并發(fā)亡呵,nginx 處理請(qǐng)求是異步非阻塞的,而apache 則是阻塞型的硫戈,在高并發(fā)下nginx 能保持低資源低消耗高性能
高度模塊化的設(shè)計(jì)锰什,編寫(xiě)模塊相對(duì)簡(jiǎn)單?
最核心的區(qū)別在于apache是同步多進(jìn)程模型,一個(gè)連接對(duì)應(yīng)一個(gè)進(jìn)程丁逝;nginx是異步的汁胆,多個(gè)連接(萬(wàn)級(jí)別)可以對(duì)應(yīng)一個(gè)進(jìn)程?
HTTP和HTTPS區(qū)別
https://www.cnblogs.com/wqhwe/p/5407468.html
sleep() 和 wait() 有什么差別??
1、每個(gè)對(duì)象都有一個(gè)鎖來(lái)控制同步訪問(wèn)霜幼,Synchronized關(guān)鍵字可以和對(duì)象的鎖交互嫩码,來(lái)實(shí)現(xiàn)同步方法或同步塊。sleep()方法正在執(zhí)行的線程主動(dòng)讓出CPU(然后CPU就可以去執(zhí)行其他任務(wù))罪既,在sleep指定時(shí)間后CPU再回到該線程繼續(xù)往下執(zhí)行(注意:sleep方法只讓出了CPU铸题,而并不會(huì)釋放同步資源鎖!W粮小丢间!);wait()方法則是指當(dāng)前線程讓自己暫時(shí)退讓出同步資源鎖驹针,以便其他正在等待該資源的線程得到該資源進(jìn)而運(yùn)行烘挫,只有調(diào)用了notify()方法,之前調(diào)用wait()的線程才會(huì)解除wait狀態(tài)柬甥,可以去參與競(jìng)爭(zhēng)同步資源鎖饮六,進(jìn)而得到執(zhí)行。(注意:notify的作用相當(dāng)于叫醒睡著的人暗甥,而并不會(huì)給他分配任務(wù)喜滨,就是說(shuō)notify只是讓之前調(diào)用wait的線程有權(quán)利重新參與線程的調(diào)度);
2撤防、sleep()方法可以在任何地方使用虽风;wait()方法則只能在同步方法或同步塊中使用;
3、sleep()是線程線程類(lèi)(Thread)的方法辜膝,調(diào)用會(huì)暫停此線程指定的時(shí)間无牵,但監(jiān)控依然保持,不會(huì)釋放對(duì)象鎖厂抖,到時(shí)間自動(dòng)恢復(fù)智亮;wait()是Object的方法,調(diào)用會(huì)放棄對(duì)象鎖统捶,進(jìn)入等待隊(duì)列霉囚,待調(diào)用notify()/notifyAll()喚醒指定的線程或者所有線程,才會(huì)進(jìn)入鎖池墙懂,不再次獲得對(duì)象鎖才會(huì)進(jìn)入運(yùn)行狀態(tài)橡卤;
正則表達(dá)式
SQL
distinct? 唯一字段
between? a and b
avg()平均數(shù)
round(a,b)保留幾位小數(shù)
group by having condition(過(guò)濾條件)
COUNT() 函數(shù)返回匹配指定條件的行數(shù)
sum()總數(shù)
跨域
跨域的原因:瀏覽器的同源策略是瀏覽器上為安全性考慮實(shí)施的非常重要的安全策略(同源:協(xié)議,域名损搬,端口三者均一致)防止惡意的網(wǎng)站竊取數(shù)據(jù)
調(diào)用方解決: - 1.隱藏跨域 - 反向代理 - apache服務(wù)器或nginx服務(wù)器配置
? ? ? ? ? ? ? ? ? ? ? ?2.CORS全稱是"跨域資源共享"(Cross-origin resource sharing),CORS需要瀏覽器和服務(wù)器同時(shí)支持碧库。目前,所有瀏覽器都支持該功能,CORS是一個(gè)W3C標(biāo)準(zhǔn)巧勤,全稱是"跨域資源共享"(Cross-origin resource sharing).它允許瀏覽器向跨源服務(wù)器嵌灰,發(fā)出XMLHttpRequest請(qǐng)求,從而克服了AJAX只能同源使用的限制颅悉。
http://www.ruanyifeng.com/blog/2016/04/cors.html
跨域又分為簡(jiǎn)單請(qǐng)求沽瞭,非簡(jiǎn)單請(qǐng)求,攜帶cookie的情況签舞。
簡(jiǎn)單請(qǐng)求只用設(shè)置addAllowedOrigin為*可解決秕脓,
自定義請(qǐng)求頭需要設(shè)置addAllowedHeader為自定義請(qǐng)求頭,
攜帶cookie后端需要setAllowCredentials同時(shí)addAllowedOrigin不能為*儒搭。前端需要withCredentials為true
保持用戶在線
1:客戶端輸入用戶名和密碼吠架,提交到服務(wù)端驗(yàn)證
2:服務(wù)端驗(yàn)證成功后,給客戶端返回以下值:
uid : 用戶的唯一標(biāo)示
time : 當(dāng)前unix時(shí)間戳
key : MD5(uid+time+"一個(gè)只有你自己知道的字符串密鑰")
3:客戶端保存以上3個(gè)值在本地搂鲫,每次HTTP請(qǐng)求時(shí)傍药,將以上3個(gè)值發(fā)送到服務(wù)端
4:服務(wù)端驗(yàn)證key,判斷如果與客戶端發(fā)送的key一致魂仍,則說(shuō)明用戶身份無(wú)誤
5:服務(wù)端每次收到請(qǐng)求時(shí)拐辽,通過(guò)當(dāng)前時(shí)間-客戶端time字段得到的差值,可以控制這個(gè)key的有效期
?二擦酌。類(lèi)似第三方登錄的方式
面向?qū)ο?/h1>
https://www.oschina.net/translate/how-i-explained-ood-to-my-wife?lang=chs&p=1
同步異步阻塞非阻塞
https://blog.csdn.net/qq_32725491/article/details/78679414
Set和Map遍歷
Set set =new HashSet();?
?Iterator it = set.iterator();?
?while (it.hasNext())?{?
?System.out.println(it.next());?
?}
Set?entryseSet=map.entrySet();
? ? ? ? for(Map.Entry entry:entryseSet) {
? ? ? ? ? ? System.out.println("第二種:"+entry.getKey()+":"+entry.getValue());
? ? ? ? }
IO流
https://blog.csdn.net/chengyuqiang/article/details/79183748
單點(diǎn)登錄
http://www.cnblogs.com/ywlaker/p/6113927.html
線程
虛擬主機(jī)俱诸,就是把一臺(tái)物理服務(wù)器劃分成多個(gè)“虛擬”的服務(wù)器,每一個(gè)虛擬主機(jī)都可以有獨(dú)立的域名和獨(dú)立的目錄
結(jié)束線程的三種方式
https://blog.csdn.net/xu__cg/article/details/52831127
使用interrupt()方法后相當(dāng)于打一個(gè)結(jié)束的標(biāo)記,在線程run方法需要些 if(isInterrupted())的邏輯
控制反轉(zhuǎn)指的是依賴反轉(zhuǎn),比如從前都是關(guān)注自己開(kāi)發(fā)讓后者依賴自己,現(xiàn)在例如spring要按照spring的標(biāo)準(zhǔn)開(kāi)發(fā),依賴于Spring才能被Spring管理,這就是控制反轉(zhuǎn)
如果兩個(gè)對(duì)象相同(equals方法返回true)赊舶,那么它們的hashCode值一定要相同
Docker鏡像和容器的關(guān)系
容器可以看作為鏡像的一個(gè)實(shí)例,像類(lèi)和對(duì)象一樣
new String()和new String(“”)都是申明一個(gè)新的空字符串睁搭,是空串不是null
Lambda表達(dá)式 stream方法是線程安全的速度慢 可以考慮使用parallelStream()方法,多線程速度快,線程不安全赶诊。原理像大數(shù)據(jù)MapReduce,將任務(wù)拆成多個(gè)小任務(wù)并行運(yùn)行再結(jié)合在一起
JDK1.8HashMap思路,通過(guò)key計(jì)算哈希值當(dāng)作數(shù)組下標(biāo),產(chǎn)生沖突則在該下標(biāo)創(chuàng)建單鏈表,由于單鏈表查詢速度慢,當(dāng)沖突數(shù)量過(guò)多時(shí)會(huì)轉(zhuǎn)化為紅黑樹(shù)提高查詢速率
HashMap容量為2的倍數(shù)原因:1.提高運(yùn)算速率 2.提高散列度 降低沖突 3.減少內(nèi)存碎片
HashMap擴(kuò)容條件 數(shù)據(jù)大于原容量3/4
常見(jiàn)狀態(tài)碼
200 請(qǐng)求成功
301 重定向新頁(yè)面
401 權(quán)限禁止訪問(wèn)
404 找不到頁(yè)面
500 服務(wù)器錯(cuò)誤
502 Bad GateWay網(wǎng)關(guān)錯(cuò)誤
504 GateWay TimeOut 網(wǎng)關(guān)無(wú)法找到服務(wù)器
如何防止SQL注入
1.正則表達(dá)式判斷
2.使用PreparedStatement預(yù)編譯語(yǔ)句
Redis常見(jiàn)數(shù)據(jù)類(lèi)型和使用場(chǎng)景
String:存儲(chǔ)一些字符串?dāng)?shù)據(jù),json化的對(duì)象或者base64編碼后的照片
hash:是一種string類(lèi)型的field和value的映射表(【hmset key field1 value1 field2 value2 ...】),適用場(chǎng)景在于如維護(hù)用戶信息中僅僅修改某個(gè)用戶的一個(gè)屬性上而不影響其他屬性
List:有序可重復(fù)的列表,可以適用于一些如消息隊(duì)列的場(chǎng)景中
Set:無(wú)序不可重復(fù)的集合,可以適用于去重的場(chǎng)景
SortSet:有序不可重復(fù)的集合,可以用于排行類(lèi)等類(lèi)似場(chǎng)景
InnoDB的行級(jí)鎖的實(shí)現(xiàn)方式
InnoDB行鎖是通過(guò)給索引上的索引項(xiàng)加鎖來(lái)實(shí)現(xiàn)的,這一點(diǎn)MySQL與Oracle不同园骆,后者是通過(guò)在數(shù)據(jù)塊中對(duì)相應(yīng)數(shù)據(jù)行加鎖來(lái)實(shí)現(xiàn)的舔痪。InnoDB這種行鎖實(shí)現(xiàn)特點(diǎn)意味著:只有通過(guò)索引條件檢索數(shù)據(jù),InnoDB才使用行級(jí)鎖锌唾,否則锄码,InnoDB將使用表鎖!
B+Tree子節(jié)點(diǎn)最少兩個(gè) 適合范圍查詢? Hash索引在數(shù)據(jù)量少的情況可能比B+樹(shù)快,但只適合= in這類(lèi)的查詢 不適合范圍查詢 因?yàn)椴樵兎绞绞峭ㄟ^(guò)哈希值計(jì)算查找對(duì)應(yīng)的key
SQL調(diào)優(yōu)思路
1.開(kāi)啟慢日志查找慢SQL
2.explain select 查找sql使用的索引
3.添加索引
最左匹配原則
mysql會(huì)一直向右匹配知道遇到范圍查詢(> < between like)就停止匹配 比如a=3 and b=3 and c>5 and d=6 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調(diào)整晌涕。
=和in可以亂序,比如a=1 and b=2 and c=3建立(a,b,c)索引可以任意排序,mysql的查詢優(yōu)化器會(huì)幫你優(yōu)化成索引可以識(shí)別的形式
MyIsam引擎在查詢的時(shí)候如果另一個(gè)session在修改數(shù)據(jù),則查詢的過(guò)程中會(huì)自動(dòng)添加一個(gè)表鎖,待查詢完畢后才會(huì)執(zhí)行修改?
MyIsam引擎支持表級(jí)鎖不支持行級(jí) InnoDB都支持
加入讀鎖(共享鎖)后不允許修改數(shù)據(jù),叫共享鎖的原因是兩個(gè)或多個(gè)session都加入讀鎖的情況下都能正常查詢數(shù)據(jù)不會(huì)阻塞
session1加入寫(xiě)鎖(排他鎖) session2讀的情況下會(huì)阻塞?session1加入寫(xiě)鎖?session2寫(xiě)鎖也會(huì)阻塞所以叫排他鎖
數(shù)據(jù)庫(kù)隔離級(jí)別
最低:讀未提交(Read Uncommitted)
第一個(gè)事務(wù)修改了數(shù)據(jù)還沒(méi)提交,第二個(gè)事務(wù)就能讀到第一個(gè)事務(wù)修改后的數(shù)據(jù),然后第一個(gè)事務(wù)回滾了 就會(huì)產(chǎn)生臟讀
讀提交(Read Committed)
第一個(gè)事務(wù)修改了數(shù)據(jù)還沒(méi)提交,第二個(gè)事務(wù)讀的是第一個(gè)事務(wù)數(shù)據(jù)修改前的數(shù)據(jù),避免了臟讀?
事務(wù)一開(kāi)啟事務(wù)后查詢數(shù)據(jù)未提交 事務(wù)二修改了數(shù)據(jù)并提交了 事務(wù)一再查詢數(shù)據(jù)發(fā)現(xiàn)和第一次不一樣,就這就不可重復(fù)度
可重復(fù)讀(Repeated Read)
事務(wù)一和事務(wù)二開(kāi)啟事務(wù) 事務(wù)一查詢數(shù)據(jù)? 事務(wù)二修改數(shù)據(jù)并提交 事務(wù)一再查詢數(shù)據(jù)與第一次一致 避免了不可重復(fù)讀 事務(wù)一提交后查詢才是最新數(shù)據(jù) 如果事務(wù)一修改了數(shù)據(jù)再提交,他也是按照事務(wù)二提交后的數(shù)據(jù)進(jìn)行修改的 例: 原數(shù)據(jù)1500 事務(wù)1查1500? 事務(wù)2 1500+100 提交 事務(wù)1查1500 事務(wù)1 -200提交 事務(wù)一查1400
事務(wù)一查詢出來(lái)三條數(shù)據(jù) 事務(wù)二添加一條數(shù)據(jù) 事務(wù)一修改所有行的數(shù)據(jù)發(fā)現(xiàn)修改了四條 這就是幻讀
串行化(Serializable)
解決幻讀
Golang并發(fā)三種模式
1.通過(guò)channel?無(wú)緩沖的通道指的是通道的大小為0滋捶,也就是說(shuō),這種類(lèi)型的通道在接收前沒(méi)有能力保存任何值渐排,它要求發(fā)送 goroutine 和接收 goroutine 同時(shí)準(zhǔn)備好炬太,才可以完成發(fā)送和接收操作
2.通過(guò)WaitGroup 主要有add done wait方法 wait只有待done到0的時(shí)候才會(huì)解除阻塞
3.在Go 1.7 以后引進(jìn)的強(qiáng)大的Context上下文,實(shí)現(xiàn)并發(fā)控制
如果Where條件全部命中 則不會(huì)用Gap鎖 只會(huì)加行鎖
如果where條件部分命中或者不會(huì)命中 則會(huì)加Gap鎖 Gap鎖就是會(huì)鎖沒(méi)被命中范圍內(nèi)的行
比如查詢id in (5,7,9)結(jié)果為5 9,則5-9范圍內(nèi)都會(huì)被鎖住?gap就是索引樹(shù)中插入新記錄的空隙
Gap鎖會(huì)用在非唯一索引或者不走索引的當(dāng)前讀中
通過(guò)next-key(行鎖+gap鎖)鎖可以在可重復(fù)讀的模式下防止幻讀發(fā)生
where過(guò)濾行 having過(guò)濾組
SETNX key value 如果key不存在則創(chuàng)建 由于是原子性操作 所以可以用在分布式鎖 不支持expire參數(shù) 所以要額外使用expire命令設(shè)置過(guò)期時(shí)間 后面用set代替了 set key value expire nx
redis中使用rpush指令和lpop指令可以簡(jiǎn)單實(shí)現(xiàn)一個(gè)異步消息隊(duì)列 blpop 隊(duì)列名 時(shí)間 代表在這個(gè)時(shí)間內(nèi)監(jiān)聽(tīng)隊(duì)列有無(wú)消息
redis subscribe命令訂閱一個(gè)主題(不需要?jiǎng)?chuàng)建) publish命令向主題推送數(shù)據(jù) 所有監(jiān)聽(tīng)的客戶端都能接收到數(shù)據(jù) 缺點(diǎn)是發(fā)送消息是無(wú)狀態(tài)的 無(wú)法保證可達(dá)性
RDB備份的兩種命令 save使用主線程創(chuàng)建快照 會(huì)造成阻塞 BGSAVE命令會(huì)Fork出一個(gè)子進(jìn)程來(lái)創(chuàng)建RDB文件 不阻塞服務(wù)器進(jìn)程
RDB+AOF混合模式 先以RDB載入數(shù)據(jù) 再用AOP追加數(shù)據(jù) 就不會(huì)導(dǎo)致數(shù)據(jù)丟失
主從模式可以讓主節(jié)點(diǎn)進(jìn)行寫(xiě)操作 子節(jié)點(diǎn)進(jìn)行讀操作 通過(guò)主節(jié)點(diǎn)創(chuàng)建RDB發(fā)送給子節(jié)點(diǎn),在這過(guò)程中將寫(xiě)操作通過(guò)aof存起來(lái),代子節(jié)點(diǎn)完成rdb文件載入后再接受aof文件實(shí)現(xiàn)數(shù)據(jù)同步
Linux對(duì)文件內(nèi)容做統(tǒng)計(jì) awk [options] 'cmd' file
sed 批量替換文本內(nèi)容
HTTP1.1多了個(gè)場(chǎng)鏈接 HTTP2是多路復(fù)用
HTTPS過(guò)程
1.客戶端先發(fā)送隨機(jī)值1和客戶端支持的加密算法
2.服務(wù)端收到請(qǐng)求后回應(yīng)隨機(jī)值2和確定的加密算法
3.服務(wù)端再回應(yīng)一個(gè)數(shù)字證書(shū),數(shù)字證書(shū)包括證書(shū)的頒發(fā)機(jī)構(gòu),過(guò)期時(shí)間,服務(wù)端公鑰和CA的簽名等
4.客戶端收到證書(shū)后進(jìn)行解析,解析的工作是交給TLS(SSL的升級(jí)版)去做的,解析沒(méi)有問(wèn)題則生成一個(gè)隨機(jī)值當(dāng)做預(yù)主秘鑰
5.客戶端通過(guò)隨機(jī)值1 2 和預(yù)主秘鑰組裝成會(huì)話秘鑰,再通過(guò)服務(wù)端的公鑰加密會(huì)話秘鑰驯耻。再將會(huì)話秘鑰發(fā)送給服務(wù)端
6.服務(wù)端通過(guò)秘鑰解密后得到隨機(jī)值1 2和預(yù)主秘鑰再組成會(huì)話秘鑰,和客戶端的會(huì)話秘鑰相同
7.客戶端通過(guò)會(huì)話秘鑰加密一條消息發(fā)送給服務(wù)端,主要驗(yàn)證服務(wù)端是否正常接受客戶端加密的消息炒考。
8.同樣服務(wù)端也會(huì)通過(guò)會(huì)話秘鑰加密一條消息回傳給客戶端可缚,如果客戶端能夠正常接受的話表明SSL層連接建立完成了
sync.Once能確保實(shí)例化對(duì)象Do方法在多線程環(huán)境只運(yùn)行一次,內(nèi)部通過(guò)互斥鎖實(shí)現(xiàn)
slice進(jìn)行切片后使用的底層數(shù)組是同一個(gè),但如果切片后的數(shù)組擴(kuò)容了則會(huì)將切片的數(shù)組拷貝一個(gè)新的進(jìn)行擴(kuò)容
Golang切片
切片的底層還是原數(shù)組,所以修改切片的值會(huì)影響原數(shù)組斋枢。如果切片進(jìn)行擴(kuò)容,則會(huì)創(chuàng)建一個(gè)新的切片(通常是兩倍 如果原長(zhǎng)度超過(guò)1024則是1.25倍)? append指向新的切片不影響原數(shù)組和切片
切片添加元素如果沒(méi)有超過(guò)原來(lái)切片的容量,則會(huì)替換覆蓋原有的元素
Golang List(雙向鏈表)
var l list.List聲明的鏈表l可以直接使用(開(kāi)箱即用)
原因是延遲初始化,就是試用的時(shí)候才初始化
1.對(duì)于Front方法和Back方法帘靡,一旦發(fā)現(xiàn)鏈表的長(zhǎng)度為0, 直接返回nil就好了
2.對(duì)于刪除元素、移動(dòng)元素瓤帚,以及一些用于插入元素的方法中描姚,只要判斷一下傳入的元素中指向所屬鏈表的指針,是否與當(dāng)前鏈表的指針相等就可以了
通過(guò)上面兩種機(jī)制不用每次都判斷該鏈表是否被初始化,彌補(bǔ)了缺陷
Channel
channel關(guān)閉過(guò)后還發(fā)送數(shù)據(jù)會(huì)異常,不過(guò)讀數(shù)據(jù)不會(huì) 所以關(guān)閉channel通常由發(fā)送方關(guān)閉
如果channel沒(méi)被close 然后通過(guò)for range讀取channel數(shù)據(jù)則會(huì)一直等待新數(shù)據(jù)戈次。反之close就不會(huì),會(huì)直接退出for
倘若通道channel的值為nil轩勘,那么這條for語(yǔ)句就會(huì)被永遠(yuǎn)地阻塞在有for關(guān)鍵字的那一行
如果select有默認(rèn)分支 其他select有阻塞則會(huì)執(zhí)行默認(rèn)分支,如果沒(méi)有默認(rèn)分支則select會(huì)阻塞直到匹配到一個(gè)case
channel關(guān)閉后? i,v<-channel? 如果channel沒(méi)數(shù)據(jù)了則返回false
Golang函數(shù)
函數(shù)參數(shù)或者返回帶有函數(shù)則稱為高級(jí)函數(shù)
Golang結(jié)構(gòu)體
func (cat *Cat)SetName(namestring) {
cat.name = name //會(huì)改變實(shí)際值
}
func (cat Cat)SetNameOfCopy(namestring) {
cat.name = name //不會(huì)改變實(shí)際值
}
Golang接口
接口被賦值后 會(huì)有一種特定的結(jié)構(gòu)進(jìn)行存儲(chǔ),包含兩個(gè)指針?lè)謩e為動(dòng)態(tài)類(lèi)型(被賦值的類(lèi)型)和動(dòng)態(tài)值(被賦值的值)
Golang不可尋址
常量的值。
基本類(lèi)型值的字面量怯邪。
算術(shù)操作的結(jié)果值绊寻。
對(duì)各種字面量的索引表達(dá)式和切片表達(dá)式的結(jié)果值。不過(guò)有一個(gè)例外悬秉,對(duì)切片字面量的索引結(jié)果值卻是可尋址的澄步。對(duì)字符串變量的索引表達(dá)式和切片表達(dá)式的結(jié)果值。
對(duì)字典變量的索引表達(dá)式的結(jié)果值和泌。
函數(shù)字面量和方法字面量村缸,以及對(duì)它們的調(diào)用表達(dá)式的結(jié)果值。
結(jié)構(gòu)體字面量的字段值武氓,也就是對(duì)結(jié)構(gòu)體字面量的選擇表達(dá)式的結(jié)果值梯皿。
類(lèi)型轉(zhuǎn)換表達(dá)式的結(jié)果值仇箱。
類(lèi)型斷言表達(dá)式的結(jié)果值。
接收表達(dá)式的結(jié)果值索烹。
總結(jié)下來(lái)是 不可變的 臨時(shí)的 不安全的都不可尋址
Golang panic recover defer
panic()函數(shù)主動(dòng)引發(fā)一個(gè) panic 括號(hào)內(nèi)參數(shù)為interfeact{}
recover函數(shù)可以恢復(fù)panic 返回值則是panic的參數(shù)
猶豫panic一旦執(zhí)行就會(huì)停止代碼繼續(xù)往下運(yùn)行 所以要通過(guò)defer來(lái)給recover運(yùn)行的機(jī)會(huì)
例:
defer func() {
????if i :=recover();i!=nil{
????fmt.Println(i)
}
????fmt.Println("Exit function main.")
}()
panic(errors.New("aaa"))
Golang測(cè)試
對(duì)于功能測(cè)試函數(shù)來(lái)說(shuō)工碾,其名稱必須以Test為前綴,并且參數(shù)列表中只應(yīng)有一個(gè)*testing.T類(lèi)型的參數(shù)聲明百姓。
對(duì)于性能測(cè)試函數(shù)來(lái)說(shuō)渊额,其名稱必須以Benchmark為前綴,并且唯一參數(shù)的類(lèi)型必須是*testing.B類(lèi)型的垒拢。
對(duì)于示例測(cè)試函數(shù)來(lái)說(shuō)旬迹,其名稱必須以Example為前綴,但對(duì)函數(shù)的參數(shù)列表沒(méi)有強(qiáng)制規(guī)定求类。
測(cè)試的實(shí)例如果成功了則會(huì)存起來(lái)作為緩存,所以第二次運(yùn)行不會(huì)顯示耗時(shí),如果代碼修改了則會(huì)重新運(yùn)行
測(cè)試的實(shí)例失敗了則不會(huì)作緩存
不用擔(dān)心緩存會(huì)影響測(cè)試的準(zhǔn)確性
t.Fatal方法作用是在打印失敗錯(cuò)誤日志之后立即終止當(dāng)前測(cè)試函數(shù)的執(zhí)行并宣告測(cè)試失敗奔垦。更具體地說(shuō),這相當(dāng)于它們?cè)谧詈蠖颊{(diào)用了t.FailNow方法尸疆。
Golang鎖
互斥鎖(Mutex) 讀鎖 (RWMutex)? 讀鎖 Lock是寫(xiě)鎖 RLock是讀鎖
讀鎖適用于讀多寫(xiě)少的情況
sync.NewCond條件變量
?參數(shù)是 Lock的實(shí)現(xiàn)
wait方法必須配合鎖使用 調(diào)用wait方法會(huì)對(duì)當(dāng)前goroutine的鎖進(jìn)行解鎖然后掛起 直到調(diào)用Signal方法或Broadcast方法喚醒才重新上鎖
Signal不需要也最好不要配合鎖使用 在鎖外調(diào)用
條件變量的Signal方法和Broadcast方法有哪些異同椿猎?
條件變量的Signal方法和Broadcast方法都是被用來(lái)發(fā)送通知的,不同的是寿弱,前者的通知只會(huì)喚醒一個(gè)因此而等待的 goroutine犯眠,而后者的通知卻會(huì)喚醒所有為此等待的 goroutine。
條件變量的Wait方法總會(huì)把當(dāng)前的 goroutine 添加到通知隊(duì)列的隊(duì)尾症革,而它的Signal方法總會(huì)從通知隊(duì)列的隊(duì)首開(kāi)始筐咧,查找可被喚醒的 goroutine。所以噪矛,因Signal方法的通知量蕊,而被喚醒的 goroutine 一般都是最早等待的那一個(gè)。這兩個(gè)方法的行為決定了它們的適用場(chǎng)景艇挨。如果你確定只有一個(gè) goroutine 在等待通知残炮,或者只需喚醒任意一個(gè) goroutine 就可以滿足要求,那么使用條件變量的Signal方法就好了雷袋。否則吉殃,使用Broadcast方法總沒(méi)錯(cuò),只要你設(shè)置好各個(gè) goroutine 所期望的共享資源狀態(tài)就可以了楷怒。
Golang Context
context.Background() 返回根節(jié)點(diǎn)
創(chuàng)建子節(jié)點(diǎn)的方法:
funcWithCancel(parent Context)(ctxContext, cancelCancelFunc)
funcWithDeadline(parent Context, deadline time.Time)(Context,CancelFunc)
funcWithTimeout(parent Context, timeout time.Duration)(Context,CancelFunc)
funcWithValue(parent Context, key interface{}, val interface{})Context
<-ctx.Done()類(lèi)似與wait? 只有執(zhí)行了cancel方法才會(huì)解除阻塞
cancel方法類(lèi)似于通知所有g(shù)o已經(jīng)完成了
ctx :=context.WithValue(context.Background(),"1","1")
newCtx:=context.WithValue(ctx, "2", "2")
value := newCtx.Value("1")
value2 := newCtx.Value("2")
fmt.Println(value)
fmt.Println(value2)
結(jié)果是? 1 2? 如果newCtx改為ctx結(jié)果則為 1 nil? 自下向上找 如果key相同則覆蓋
Golang sync.Pool
自我理解? 使用通常先用Get方法再用Put方法 Get就是從臨時(shí)對(duì)象池中查找有沒(méi)有值 沒(méi)有則New一個(gè)出來(lái) 然后再調(diào)用Put方法存進(jìn)去? 下次再Get的時(shí)候就不是重新創(chuàng)建新的對(duì)象了
Go 語(yǔ)言運(yùn)行時(shí)系統(tǒng)中的垃圾回收器蛋勺,所以在每次開(kāi)始執(zhí)行之前,都會(huì)對(duì)所有已創(chuàng)建的臨時(shí)對(duì)象池中的值進(jìn)行全面地清除鸠删。
Golang sync.Map
由于這個(gè)map不支持泛型 所以通過(guò)自己的方法去規(guī)定傳入類(lèi)型 比如創(chuàng)建一個(gè)結(jié)構(gòu)體為
type ConcurrentMap struct {?
????m sync.Map?
????keyType reflect.Type?
????valueType reflect.Type
}
然后通過(guò)包裝原本map方法對(duì)類(lèi)型做判斷
比如:?
func (cMap *ConcurrentMap) Load(key interface{}) (value interface{}, ok bool) {?
????if reflect.TypeOf(key) != cMap.keyType {?
????????return?
????}?
????return cMap.m.Load(key)
}
sync.map適合讀多寫(xiě)少的場(chǎng)景,在幾個(gè)寫(xiě)操作當(dāng)中抱完,新增鍵值對(duì)的操作對(duì)并發(fā)安全字典的性能影響是最大的,其次是刪除操作刃泡,最后才是修改操作巧娱。
sync.map的實(shí)現(xiàn)由兩個(gè)map完成,第一個(gè)是read(原子操作) 第二個(gè)是dirty(帶鎖操作) read類(lèi)型是sync/atomic.Value類(lèi)型所以不會(huì)用到鎖而是原子操作? read只能對(duì)鍵值改變不能增減數(shù)量,dirty即可變成鍵值又可修改數(shù)量,dirty的數(shù)據(jù)會(huì)比read全,在查詢r(jià)ead不到結(jié)果一定次數(shù)的情況下dirty會(huì)轉(zhuǎn)為read 然后將dirty置nil
sync.Map在查找指定的鍵所對(duì)應(yīng)的值的時(shí)候碉怔,總會(huì)先去只讀字典中尋找,并不需要鎖定互斥鎖禁添。只有當(dāng)確定“只讀字典中沒(méi)有撮胧,但臟字典中可能會(huì)有這個(gè)鍵”的時(shí)候,它才會(huì)在鎖的保護(hù)下去訪問(wèn)臟字典老翘。
相對(duì)應(yīng)的芹啥,sync.Map在存儲(chǔ)鍵值對(duì)的時(shí)候,只要只讀字典中已存有這個(gè)鍵铺峭,并且該鍵值對(duì)未被標(biāo)記為“已刪除”墓怀,就會(huì)把新值存到里面并直接返回,這種情況下也不需要用到鎖卫键。否則傀履,它才會(huì)在鎖的保護(hù)下把鍵值對(duì)存儲(chǔ)到臟字典中。這個(gè)時(shí)候莉炉,該鍵值對(duì)的“已刪除”標(biāo)記會(huì)被抹去钓账。