歡迎關(guān)注公眾號“Tim在路上”
1.聽說你對JVM有點研究疹尾,講一講JVM的內(nèi)存模型吧(我說虛擬機棧上忍,本地方法棧,程序計數(shù)器纳本,堆窍蓝,方法區(qū))
總的有什么,生命周期繁成,每一個
- JVM 的分區(qū) 吓笙,線程私有,線程共享巾腕,直接內(nèi)存
- 線程私有的生命周期和線程相同面睛,線程共享的和虛擬機的生命周期相同絮蒿。
- java虛擬機棧是將方法的變量,出入口參數(shù)等以棧幀的形式存入叁鉴,虛擬機中只有一個堆土涝,堆中存入的是new出的對象,而且堆是垃圾回收的主要場所幌墓。方法區(qū)主要存儲類信息但壮,常量,靜態(tài)變量和即時編譯器后的代碼常侣。
2.JVM的垃圾回收機制了解嗎蜡饵?有哪些垃圾回收算法?原理是什么(我就說出引用計數(shù)法和可達性分析法)
- JVM 的垃圾回收胳施,主要是在jVM的堆區(qū)胸蛛,采用的分區(qū)回收镜遣。
- java堆可以分為祝拯,新生代厂僧,老年代和元數(shù)據(jù)區(qū)鸟召。
- 主要的垃圾回收算法有胆绊,復制算法,標記清除算法和標記整理算法欧募。
- 原理是 引用計數(shù)法和 GC roots 可達性分析進行的压状。
3.數(shù)據(jù)庫了解嗎?講出兩個數(shù)據(jù)庫引擎跟继?
MyISAM 和 InnoDB;
- 他們之間的區(qū)別是种冬, InnoDB 支持事務,MyISAM 不支持事務舔糖,InnoDB 支持外鍵娱两,MyISAM不支持外鍵;
InnoDB 支持行級鎖金吗,MyISAM 只支持表級鎖十兢,InnoDB 支持崩潰后恢復,MyISAM 不支持崩潰后恢復摇庙,其次是他們索引都是用的B+樹旱物,但是也不完全一樣。
MyISAM 適合于查多更新少的情況以及存在大量整表count的情況卫袒。
4.OSI和TCP/IP都有哪些層宵呛?
OSI 的 七層網(wǎng)絡模型,主要有 物理層夕凝,數(shù)據(jù)鏈路層宝穗,網(wǎng)絡層户秤,傳輸層,會話層讽营,表示層以及應用層虎忌;
TCP/IP 網(wǎng)絡接口層,網(wǎng)絡層橱鹏,傳輸層膜蠢,應用層
應用層,HTTP,DNS,FTP等莉兰, 傳輸層主要有挑围,TCP,UDP協(xié)議
網(wǎng)絡層主要有,IP,ICMP,ARP,網(wǎng)絡接口層 PPP
5.TCP/IP的運輸層和網(wǎng)絡層做了什么糖荒?起到了什么作用杉辙?
網(wǎng)絡層主要是,通過路由選擇為捶朵,為報文和分組選擇合適路徑蜘矢,進行流量控制和差錯校驗;尋址综看;
傳輸層主要是品腹,起承上啟下作用,向用戶提供可靠的端到端的差錯和流量控制红碑,保證報文正確傳輸舞吭。傳輸層向高層提供面向連接和面向無連接的兩種服務。
IP協(xié)議是網(wǎng)際互聯(lián)層最重要的協(xié)議析珊,它提供的是一個不可靠羡鸥、無連接的數(shù)據(jù)報傳遞服務
6.HTTP協(xié)議了解嗎?能和我說說HTTP請求報文的結(jié)構(gòu)嗎忠寻?(這個問題我好像理解錯題意了惧浴,GG)
HTTP 請求報文結(jié)構(gòu),主要有奕剃,請求行(請求方法赶舆,url,http版本),請求頭(k-v對祭饭,把詳細信息高速服務端芜茵,語言類型,長連接等)倡蝙,空行(請求頭結(jié)束)九串,請求報文主體(post有,發(fā)送給客戶端的信息)
HTTP 響應報文結(jié)構(gòu),起始行(協(xié)議版本猪钮,返回狀態(tài)碼品山,返回信息),響應頭烤低,空行肘交,返回內(nèi)容;
7.假如我在瀏覽器輸入一個網(wǎng)址扑馁,按下回車涯呻,你能告訴我用了哪些協(xié)議,發(fā)生了什么嗎腻要?(我說應用層先通過DNS協(xié)議把主機名轉(zhuǎn)換成IP复罐,然后發(fā)送HTTP請求報文,運輸層TCP協(xié)議將報文分成報文段繼續(xù)往網(wǎng)絡層傳輸雄家,網(wǎng)絡層負責轉(zhuǎn)發(fā)至目的主機效诅,然后服務器巴拉巴拉的)
- 瀏覽器查詢域名IP, 這個過程會使用 DNS 協(xié)議進行查找,先進行本地hosts和緩存的查找趟济,進行遞歸查詢乱投;
- 瀏覽器向服務器發(fā)送HTTP請求,這個主要TCP協(xié)議顷编,建立TCP連接時使用IP協(xié)議篡腌,OSPF協(xié)議,ip數(shù)據(jù)包在路由之間的旋轉(zhuǎn)協(xié)議勾效,ARP ,ip 轉(zhuǎn)MAC地址協(xié)議,HTTP 協(xié)議
- 服務器返回 HTML 響應
- 瀏覽器展示 HTML
8.你能和我說說操作系統(tǒng)的核心內(nèi)容嗎叛甫?(我說了內(nèi)存管理层宫,線程進程調(diào)度,磁盤調(diào)度其监,CPU啥的巴拉巴拉的萌腿,說著說著面試官讓我停了,說差不多可以了)
操作系統(tǒng)是一組管理計算機硬件和軟件抖苦,同時調(diào)度資源的程序集合毁菱。
操作系統(tǒng)主要提供,內(nèi)存分配回收锌历,空間擴充贮庞,地址轉(zhuǎn)換和存儲保護。
操作系統(tǒng)利用虛擬存儲技術(shù)究西,進行空間的擴充窗慎。
虛擬內(nèi)存的基本思想是,每個進程有用獨立的邏輯地址空間,內(nèi)存被分為大小相等的多個塊,稱為頁(Page).每個頁都是一段連續(xù)的地址遮斥。
9.Spring的bean了解嗎峦失?他的生命周期說一說?(我就說出了 實例化术吗,屬性賦值尉辑,初始化,銷毀)
- 根據(jù)配置文件中的信息较屿,實例化Bean, 主要包括掃描配置文件包隧魄,加載@Service 等bean,進行配置
- 使用依賴注入填充屬性,@Autowared和 @Resource
- 如果bean 實現(xiàn)了BeanNameAware接口吝镣,通過bean id 調(diào)用setBeanName()
- 如果bean 實現(xiàn)了BeanFactoryAware接口堤器,通過傳入factory自身,調(diào)用setBeanFactory方法
- 如果是實現(xiàn)呢BeanApplicationAware接口末贾,通過傳遞Spring上下文調(diào)用set方法闸溃。
- bean如何實現(xiàn)和BeanPostProcessors方法,則調(diào)用拱撵,進行一些屬性值性等操作
- 如果bean 實現(xiàn) init-method方法調(diào)用初始化
- 調(diào)用BeanPostProcessors方法
- 調(diào)用 bean 的 destroy()方法
- 如果為bean指定了destroy方法(<bean>的destroy-method屬性)辉川,那么將調(diào)用它
10.Spring的AOP了解嗎?知道實現(xiàn)原理的嗎拴测?知道什么時候創(chuàng)建代理對象嗎乓旗?(我說實現(xiàn)原理是動態(tài)代理)
Spring AOP是基于動態(tài)代理實現(xiàn)的,Spring AOP 支持方法和屬性級別的Pointcut集索;
主要有兩種屿愚,JDK 動態(tài)代理,一種是通過 cglib 的動態(tài)代理
可以通過開啟proxy-target-class = true 使用 cglib方式
使用cglib 方式可以對沒實現(xiàn)接口的類方法進行aop,比如 controller
11.hashmap這個東西是不是線程安全的拔窬!妆距?hashmap線程不安全的原因是啥,結(jié)合1.7和1.8說說函匕?你覺得1.7當中的那個死循環(huán)是導致它不安全的原因嘛娱据?
hashMap 不是線程安全的;
- 首先jMM內(nèi)存模型盅惜,線程只能先和自己的工作內(nèi)存交互中剩,之后共享內(nèi)存,會出現(xiàn)讀寫數(shù)據(jù)不一致的問題抒寂;
- 如果寫線程唯一结啼,讀線程多個還會造成線程安全問題嗎?
如果在集合迭代的過程中屈芜,iterator(迭代器)不知道集合發(fā)生了修改(add/remove)操作妆棒,就會報錯 如何實現(xiàn)遍歷集合的同時進行修改:讓iterator知道,即用iterator自帶的remove方法:iterator.remove();
1.寫線程唯一、讀線程不確定糕珊,沒有迭代操作动分。使用hashmap不會存在程序不安全,多就是發(fā)生數(shù)據(jù)不一致性的問題红选。 2. 場景2:寫線程唯一澜公、讀線程不確定,有迭代操作喇肋,此時不能使用hashmap坟乾,會存在fastfail問題 3. 場景3: 讀寫線程是同一個,且唯一蝶防,有迭代操作甚侣,此時注意不能通過集合方法remove或者add更改,只能通過iterator內(nèi)方法來 更新间学。不然會存在fastfail問題殷费。
12.那這個concurrenthashmap是線程安全的嗎?它們兩個之間的區(qū)別是什么低葫?
利用CAS + synchronized 實現(xiàn)node節(jié)點粒度的并發(fā)
resize的時候單線程構(gòu)建一個nextTable(2倍原容量)详羡、多線程擴容 put的時候如果檢測到需要插入的位置被forward節(jié)點占有,就幫助擴容嘿悬、如果檢測到的節(jié)點非空且不是forward節(jié)點实柠,對節(jié)點加syn鎖, 進行節(jié)點插入 get的時候不加鎖善涨,可多線程查找 remove的時候如果檢測到需要刪除的位置被forward節(jié)點占有窒盐,就幫助擴容、如果不是钢拧,則對節(jié)點加syn鎖蟹漓,進行節(jié)點刪除
13.hashmap在1.8引入了紅黑樹,那為什么要引入紅黑樹娶靡?
加快檢索速度,同時紅黑樹相比avl樹看锉,在檢索的時候效率其實差不多姿锭,都是通過平衡來二分查找。但對于插入刪除等操作效率提高很多伯铣。紅黑樹不像avl樹一樣追求絕對的平衡呻此,他允許局部很少的不完全平衡,這樣對于效率影響不大腔寡,但省去了很多沒有必要的調(diào)平衡操作焚鲜,avl樹調(diào)平衡有時候代價較大,所以效率不如紅黑樹。
14.你能說說concurrenthashmap和hashmap的put過程嗎忿磅?
HashMap put流程
1.通過hash函數(shù)計算key的hash值糯彬,調(diào)用putVal方法
2.如果hash表為空,調(diào)用resize()方法創(chuàng)建一個hash表
3.根據(jù)hash值索引hash表對應桶位置葱她,判斷該位置是否有hash碰撞
3.1 沒有碰撞撩扒,直接插入映射入hash表
3.2 有碰撞,遍歷桶中節(jié)點
3.2.1 第一個節(jié)點匹配吨些,記錄該節(jié)點
3.2.2 第一個節(jié)點沒有匹配搓谆,桶中結(jié)構(gòu)為紅黑樹結(jié)構(gòu),按照紅黑樹結(jié)構(gòu)添加數(shù)據(jù)豪墅,記錄返回值
3.2.3 第一個節(jié)點沒有匹配泉手,桶中結(jié)構(gòu)是鏈表結(jié)構(gòu)。遍歷鏈表偶器,找到key映射節(jié)點斩萌,記錄,退出循環(huán)状囱。
ConcurtHashMap put流程
- 計算Hash值
- 判斷當前的table是否為空术裸,如果為空則進行初始化操作。
- table不為空則根據(jù)Hash值找到對應下標的節(jié)點
下標節(jié)點為空則通過cas將新節(jié)點放入亭枷,失敗進入循環(huán) - 如果為ForwardingNode類型袭艺,則表示當前其他線程正在擴容,則進入helpTransfer()協(xié)助擴容
- 如果不為空且是普通節(jié)點叨粘,則對節(jié)點上鎖猾编,往鏈表或者紅黑樹添加。
- cas更新baseCount升敲,并判斷是否需要擴容
HashMap 的擴容過程答倡?
1、首先建立新數(shù)組newTable驴党、為原數(shù)組的兩倍
2瘪撇、將原數(shù)組hash到新數(shù)組中,hash & (newLength-1)港庄,
3倔既、如果原數(shù)組節(jié)點只有一個頭節(jié)點,則hash到新數(shù)組直接放入
4鹏氧、如果原數(shù)組e是樹節(jié)點渤涌,則將其split(保持順序分裂成兩個樹節(jié)點TreeNode list、list過長則轉(zhuǎn)化成樹把还,不然則徹底轉(zhuǎn)成node list)
5实蓬、如果是鏈表茸俭,則保持原數(shù)組中鏈表的順序,hash到新數(shù)組中
CurcurtHashMap 進行擴容安皱?
resize的時候單線程構(gòu)建一個nextTable(2倍原容量)调鬓、多線程擴容 put的時候如果檢測到需要插入的位置被forward節(jié)點占有,就幫助擴容练俐、如果檢測到的節(jié)點非空且不是forward節(jié)點袖迎,對節(jié)點加syn鎖, 進行節(jié)點插入 get的時候不加鎖腺晾,可多線程查找 remove的時候如果檢測到需要刪除的位置被forward節(jié)點占有燕锥,就幫助擴容甘邀、如果不是隧膘,則對節(jié)點加syn鎖肖粮,進行節(jié)點刪除
15.紅黑樹你能介紹下嗎消痛?它的左旋右旋是怎么樣的治拿?為什么要左旋右旋呢省骂?紅黑樹便于查找元素嗎举户?
紅黑樹是二茬查找樹的一種尤仍,每一個節(jié)點要么是黑要么是紅蕉世,父節(jié)點是黑蔼紧,葉子節(jié)點是黑(nil節(jié)點),每一個紅節(jié)點的兩個子節(jié)點都是黑的狠轻,任意節(jié)點到每個葉子節(jié)點上都包含相同數(shù)量的黑節(jié)點奸例,不存在一個子樹高度是其他的2倍;
所以它的查找最壞時間復雜度為O(2lgN)向楼,也即整顆樹剛好紅黑相隔的時候查吊;
7.哪些情況會發(fā)生OOM?
堆內(nèi)存空間不足湖蜕,一般是內(nèi)存泄漏和數(shù)據(jù)峰值
內(nèi)存泄漏的代碼逻卖,HashMap 的key 是一個對象但是沒實現(xiàn)equals方法
發(fā)生OOM 因為 棧 和 堆的空間是可以動態(tài)變化的,當棧和堆空間不足昭抒,同時系統(tǒng)的空間不足時评也,進行申請空間就會發(fā)生 OOM 異常。
即使有足夠的物理內(nèi)存可用灭返,只要達到堆空間設置的大小限制盗迟,此異常仍然會被觸發(fā)。
16.問問spring吧婆殿,說說ioc诈乒,了解bean的生命周期嗎罩扇?再講一下ioc容器的初始化過程吧婆芦。
spring 容器啟動流程:
- 刷新容器怕磨,標記容器啟動
- 將配置信息解析,注冊到BeanFactory
- 設置 BeanFactory 的類加載器消约,添加幾個 BeanPostProcessor肠鲫,手動注冊幾個特殊的 bean
- Bean 如果實現(xiàn)了BeanFactoryPostProcessor 接口,那么在容器初始化以后或粮,Spring 會負責調(diào)用里面的 postProcessBeanFactory 方法导饲。這里是提供給子類的擴展點,到這里的時候氯材,所有的 Bean 都加載渣锦、注冊完成了,但是都還沒有初始化具體的子類可以在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實現(xiàn)類或做點什么事氢哮,用于初始化前做點什么(例如修改屬性的值袋毙,修改bean的scope為單例或者多例
- 初始化當前的事件廣播器
- 初始化所有的 singleton beans(lazy-init 的除外
- 廣播applicationcontext初始化完成
spring MVC 啟動流程:
總體概括spring的啟動過程:
1.首先,對于一個web應用冗尤,其部署在web容器中听盖,web容器提供其一個全局的上下文環(huán)境,這個上下文就是ServletContext裂七,其為后面的spring IoC容器提供宿主環(huán)境皆看;
2.其 次,在web.xml中會提供有contextLoaderListener背零。在web容器啟動時腰吟,會觸發(fā)容器初始化事件,此時 contextLoaderListener會監(jiān)聽到這個事件捉兴,其contextInitialized方法會被調(diào)用蝎困,在這個方法中,spring會初始 化一個啟動上下文倍啥,這個上下文被稱為根上下文禾乘,即WebApplicationContext,這是一個接口類虽缕,確切的說始藕,其實際的實現(xiàn)類是 XmlWebApplicationContext。這個就是spring的IoC容器氮趋,其對應的Bean定義的配置由web.xml中的 context-param標簽指定伍派。在這個IoC容器初始化完畢后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為屬性Key剩胁,將其存儲到ServletContext中诉植,便于獲取昵观;
3.再 次晾腔,contextLoaderListener監(jiān)聽器初始化完畢后舌稀,開始初始化web.xml中配置的Servlet,這里是DispatcherServlet灼擂,這個servlet實際上是一個標準的前端控制器壁查,用以轉(zhuǎn)發(fā)、匹配剔应、處理每個servlet請 求睡腿。DispatcherServlet上下文在初始化的時候會建立自己的IoC上下文,用以持有spring mvc相關(guān)的bean峻贮。在建立DispatcherServlet自己的IoC上下文時席怪,會利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE 先從ServletContext中獲取之前的根上下文(即WebApplicationContext)作為自己上下文的parent上下文。有了這個 parent上下文之后纤控,再初始化自己持有的上下文何恶。這個DispatcherServlet初始化自己上下文的工作在其initStrategies方 法中可以看到,大概的工作就是初始化處理器映射嚼黔、視圖解析等细层。這個servlet自己持有的上下文默認實現(xiàn)類也是 mlWebApplicationContext。初始化完畢后唬涧,spring以與servlet的名字相關(guān)(此處不是簡單的以servlet名為 Key疫赎,而是通過一些轉(zhuǎn)換,具體可自行查看源碼)的屬性為屬性Key碎节,也將其存到ServletContext中捧搞,以便后續(xù)使用。這樣每個servlet 就持有自己的上下文狮荔,即擁有自己獨立的bean空間胎撇,同時各個servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定義的那些 bean
11.知道beanpostprocessor嘛殖氏?
BeanPostProcessor即晚树,Bean的后置處理器,它的作用就是在Bean的初始化方法前跟后進行攔截處理
17. JAVA中集合和數(shù)組的區(qū)別雅采?
- 數(shù)組聲明了它容納的元素類型爵憎,而集合不聲明;
- 數(shù)組長度是固定的婚瓜,集合是可以改變的宝鼓;
- 數(shù)組里面只有一個類型,集合沒有聲明泛型可以添加多個類型巴刻;
- 數(shù)組是內(nèi)置數(shù)據(jù)類型愚铡,效率高
- 集合可以面向接口編程,具有封裝胡陪,繼承沥寥,多態(tài)的特性正蛙;
18. Redis 持久化的方式?
redis 持久化有兩種方式 RDB快照营曼, AOF 命令保存
19. OSI 七層網(wǎng)絡模型?
- 物理層愚隧,利用傳輸介質(zhì)蒂阱,為數(shù)據(jù)鏈路層提供網(wǎng)絡服務,實現(xiàn)比特流透明傳輸狂塘。
- 數(shù)據(jù)鏈路層录煤,通過差錯控制和流量控制,使有差錯的物理線路變?yōu)闊o差錯的數(shù)據(jù)鏈路荞胡。
- 網(wǎng)絡層妈踊,通過路由算法為報文和數(shù)組選擇適當?shù)穆窂健?/li>
- 傳輸層,向用戶提供可靠的端到端的差錯控制泪漂,流量控制廊营;
- 應用層,向用戶提供服務萝勤。
20. 跳表是什么露筒?
跳表就是加索引的鏈表。
它的插入和刪除的時間復雜度是 O(log(n))
21. Spring 中的過濾器敌卓?
過濾器是請求到達Servlet 之前進入
攔截器是AOP 的一種策略慎式,用于某個方法或者某個字段進行攔截。
過濾器是在 Servlet 規(guī)范中定義的趟径,是由 Servlet 容器支持的瘪吏;攔截器是在 Spring 容器內(nèi)的,由 Spring 框架支持蜗巧。
過濾器是基于函數(shù)的回調(diào)掌眠,而攔截器是基于 Java 反射機制的
過濾器可以修改 request,而攔截器則不能
過濾器需要在 servlet 容器中實現(xiàn)幕屹,攔截器可以適用于 JavaEE扇救、JavaSE 等各種環(huán)境
攔截器可以調(diào)用 IOC 容器中的各種依賴,而過濾器不能
過濾器只能在請求的前后使用香嗓,而攔截器可以詳細到每個方法
22. JAVA 自動裝箱和拆箱
自動裝箱就是Java自動將原始類型值轉(zhuǎn)換成對應的對象迅腔,比如將int的變量轉(zhuǎn)換成Integer對象,這個過程叫做裝箱靠娱,反之將Integer對象轉(zhuǎn)換成int類型值沧烈,這個過程叫做拆箱
自動裝箱有一個問題,那就是在一個循環(huán)中進行自動裝箱操作的情況像云,如下面的例子就會創(chuàng)建多余的對象锌雀,影響程序的性能蚂夕。
Integer sum = 0;
for(int i=1000; i<5000; i++){
sum+=i;
}
上面的代碼sum+=i可以看成sum = sum + i,但是+這個操作符不適用于Integer對象腋逆,首先sum進行自動拆箱操作婿牍,進行數(shù)值相加操作,最后發(fā)生自動裝箱操作轉(zhuǎn)換成Integer對象惩歉。
23. 什么是事務等脂?
事務就是一系列操作,他們要符合ACID,要么全成功撑蚌,要么全失斏弦!;
24. 進程和線程上下文切換了什么争涌,共享了什么粉楚?
進程活動所需要的信息成為上下文,主要包括亮垫,進程id,指向可執(zhí)行文件的指針模软,棧,靜態(tài)和動態(tài)分配變量的內(nèi)存饮潦,處理器寄存器撵摆;
線程共享進程,線程的上下文害晦,棧特铝,狀態(tài),寄存器
進程的切換壹瘟,主要是頁目錄切換新的地址空間鲫剿,切換內(nèi)核棧,切換硬件上下文
線程的切換是不需要切換地址空間稻轨,他們共享進程地址空間
25. 進程獨占什么灵莲、切換時候內(nèi)核做了什么?
進程在操作系統(tǒng)內(nèi)核程序臨界區(qū)中:進入臨界區(qū)后殴俱,需要獨占式地訪問共享數(shù)據(jù)政冻,理論上必須加鎖,以防止其他并行程序進入线欲,在解鎖前不應切換到其他進程運行明场,以加快該共享數(shù)據(jù)的釋放
操作系統(tǒng)內(nèi)核將原進程的現(xiàn)場信息推入到當前進程的內(nèi)核堆棧來保存它們,并更新堆棧指針李丰。內(nèi)核完成從新進程的內(nèi)核棧中裝入新進程的現(xiàn)場信息苦锨、更新當前運行進程空間指針、重設PC寄存器等相關(guān)工作之后,開始運行新的進程舟舒。
26. 為什么要有ip和mac拉庶、mac地址是如何來的?
IP地址,相信大家都很熟悉秃励,即指使用TCP/IP協(xié)議指定給主機的32位地址氏仗。
每個以太網(wǎng)設備在出廠時都有一個唯一的MAC地址了
每臺主機都分配唯一的IP地址了,為什么還要在網(wǎng)絡設備(如網(wǎng)卡夺鲜,集線器皆尔,路由器等)生產(chǎn)時內(nèi)嵌一個唯一的MAC地址呢?主要原因有以下幾點:(1)IP地址的分配是根據(jù)網(wǎng)絡的拓樸結(jié)構(gòu)谣旁,而不是根據(jù)誰制造了網(wǎng)絡設置。若將高效的路由選擇方案建立在設備制造商的基礎上而不是網(wǎng)絡所處的拓樸位置基礎上滋早,這種方案是不可行的榄审。(2)當存在一個附加層的地址尋址時,設備更易于移動和維修杆麸。例如搁进,如果一個以太網(wǎng)卡壞了,可以被更換昔头,而無須取得一個新的IP地址饼问。如果一個IP主機從一個網(wǎng)絡移到另一個網(wǎng)絡,可以給它一個新的IP地址揭斧,而無須換一個新的網(wǎng)卡莱革。(3)無論是局域網(wǎng),還是廣域網(wǎng)中的計算機之間的通信讹开,最終都表現(xiàn)為將數(shù)據(jù)包從某種形式的鏈路上的初始節(jié)點出發(fā)盅视,從一個節(jié)點傳遞到另一個節(jié)點,最終傳送到目的節(jié)點旦万。數(shù)據(jù)包在這些節(jié)點之間的移動都是由ARP(Address Resolution Protocol:地址解析協(xié)議)負責將IP地址映射到MAC地址上來完成的闹击。下面我們來通過一個例子看看IP地址和MAC地址是怎樣結(jié)合來傳送數(shù)據(jù)包的。
27. 數(shù)據(jù)庫語句 count(*)成艘、count(1)赏半、count(字段)
count(1) 和 count(*) 都會統(tǒng)計包含null 的字段,count(字段) 不會統(tǒng)計為null的數(shù)據(jù)
列名為主鍵淆两,count(列名)會比count(1)快
列名不為主鍵断箫,count(1)會比count(列名)快
如果表多個列并且沒有主鍵,則 count(1) 的執(zhí)行效率優(yōu)于 count()
如果有主鍵秋冰,則 select count(主鍵)的執(zhí)行效率是最優(yōu)的
如果表只有一個字段瑰枫,則 select count()最優(yōu)。
1.如果在開發(fā)中確實需要用到count()聚合,那么優(yōu)先考慮count()光坝,因為mysql數(shù)據(jù)庫本身對于count()做了特別的優(yōu)化處理尸诽。
有主鍵或聯(lián)合主鍵的情況下,count()略比count(1)快一些盯另。
沒有主鍵的情況下count(1)比count()快一些性含。
如果表只有一個字段,則count(*)是最快的鸳惯。
2.使用count()聚合函數(shù)后商蕴,最好不要跟where age = 1;這樣的條件芝发,會導致不走索引绪商,降低查詢效率。除非該字段已經(jīng)建立了索引辅鲸。使用count()聚合函數(shù)后刀崖,若有where條件并齐,且where條件的字段未建立索引趟佃,則查詢不會走索引混驰,直接掃描了全表。
3.count(字段),非主鍵字段刻炒,這樣的使用方式最好不要出現(xiàn)决采。因為它不會走索引.
28. group by、order by坟奥、distinct
order by 一種是通過索引取得有序數(shù)據(jù)树瞭,不需要進行任何排序操作,即可將有序數(shù)據(jù)返回客戶端
另一種是通過mysql的排序算法爱谁,將存儲引擎中數(shù)據(jù)排序移迫,返回客戶端。
group by 實際上也是同樣的操作管行,與order by 相比group by 主要是多了排序之后的分組操作
- 使用松散的索引掃描group by
在沒有where語句必須經(jīng)過全索引掃描的時候厨埋,松散索引掃描需要讀取的鍵值數(shù)量與分組的組數(shù)量一樣多,也就是說比實際存在的鍵值數(shù)目要少很多捐顷。而在WHERE子句包含范圍判斷式或者等值表達式的時候荡陷,松散索引掃描查找滿足范圍條件的每個組的第1個關(guān)鍵字,并且再次讀取盡可能最少數(shù)量的關(guān)鍵字
- 使用緊湊的索引掃描group by
當GROUP BY條件字段并不連續(xù)或者不是索引前綴部分的時候迅涮,MySQL Query Optimizer無法使用松散索引掃描废赞,設置無法直接通過索引完成GROUP BY操作,因為缺失的索引鍵信息無法得到叮姑。但是唉地,如果Query語句中存在一個常量值來引用缺失的索引鍵据悔,則可以使用緊湊索引掃描完成GROUP BY操作,因為常量填充了搜索關(guān)鍵字中的“差距”耘沼,可以形成完整的索引前綴极颓。這些索引前綴可以用于索引查找。而如果需要排序GROUP BY結(jié)果群嗤,并且能夠形成索引前綴的搜索關(guān)鍵字菠隆,MySQL還可以避免額外的排序操作,因為使用有順序的索引的前綴進行搜索已經(jīng)按順序檢索到了所有關(guān)鍵字狂秘。
- 使用臨時表實現(xiàn)GROUP BY
MySQL在進行GROUP BY操作的時候要想利用所有骇径,必須滿足GROUP BY的字段必須同時存放于同一個索引中,且該索引是一個有序索引(如Hash索引就不能滿足要求)者春。而且破衔,并不只是如此,是否能夠利用索引來實現(xiàn)GROUP BY還與使用的聚合函數(shù)也有關(guān)系钱烟。
1.盡可能讓MySQL可以利用索引來完成GROUP BY操作晰筛,當然最好是松散索引掃描的方式最佳。在系統(tǒng)允許的情況下忠售,我們可以通過調(diào)整索引或者調(diào)整Query這兩種方式來達到目的传惠;
2.當無法使用索引完成GROUP BY的時候迄沫,由于要使用到臨時表且需要filesort稻扬,所以我們必須要有足夠的sort_buffer_size來供MySQL排序的時候使用,而且盡量不要進行大結(jié)果集的GROUP BY操作羊瘩,因為如果超出系統(tǒng)設置的臨時表大小的時候會出現(xiàn)將臨時表數(shù)據(jù)copy到磁盤上面再進行操作泰佳,這時候的排序分組操作性能將是成數(shù)量級的下降;
DISTINCT實際上和GROUP BY的操作非常相似尘吗,只不過是在GROUP BY之后的每組中只取出一條記錄而已逝她。所以,DISTINCT的實現(xiàn)和GROUP BY的實現(xiàn)也基本差不多睬捶,沒有太大的區(qū)別黔宛。同樣可以通過松散索引掃描或者是緊湊索引掃描來實現(xiàn),當然擒贸,在無法僅僅使用索引即能完成DISTINCT的時候臀晃,MySQL只能通過臨時表來完成。但是介劫,和GROUP BY有一點差別的是徽惋,DISTINCT并不需要進行排序。也就是說座韵,在僅僅只是DISTINCT操作的Query如果無法僅僅利用索引完成操作的時候险绘,MySQL會利用臨時表來做一次數(shù)據(jù)的“緩存”,但是不會對臨時表中的數(shù)據(jù)進行filesort操作。當然宦棺,如果我們在進行DISTINCT的時候還使用了GROUP BY并進行了分組瓣距,并使用了類似于MAX之類的聚合函數(shù)操作,就無法避免filesort了
29. 一條sql語句渺氧,數(shù)據(jù)庫做了什么旨涝?
- 客戶端發(fā)送一條查詢給服務器;
- 服務器先會檢查查詢緩存侣背,如果命中了緩存白华,則立即返回存儲在緩存中的結(jié)果。否則進入下一階段贩耐;
- 服務器端進行SQL解析弧腥、預處理,再由優(yōu)化器生成對應4的執(zhí)行計劃潮太;
- MySQL根據(jù)優(yōu)化器生成的執(zhí)行計劃管搪,調(diào)用存儲引擎的API來執(zhí)行查詢;
- 將結(jié)果返回給客戶端铡买。
一條sql 的更新過程
1更鲁、首先執(zhí)行器會找引擎取id=1這條數(shù)據(jù);
2奇钞、因為id是主鍵澡为,所以使用樹來找到一行數(shù)據(jù)。不過引擎先去內(nèi)存中查找是否有這一頁數(shù)據(jù)景埃;
3媒至、如果有則直接返回數(shù)據(jù)給執(zhí)行器;如果沒有就會去磁盤把數(shù)據(jù)讀入到內(nèi)存中谷徙,然后返回數(shù)據(jù)給執(zhí)行器拒啰。
4、執(zhí)行器就會執(zhí)行C+10操作完慧;
5谋旦、執(zhí)行器生成新的一行數(shù)據(jù);
6屈尼、再調(diào)用 InnoDB 引擎的寫入接口册着,把數(shù)據(jù)更新到內(nèi)存中;
7鸿染、InnoDB 引擎寫入 redo log 日志指蚜,標記狀態(tài)為 prepare,并且告訴執(zhí)行器已經(jīng)更新數(shù)據(jù)完成涨椒,可以隨時提交事務摊鸡;
8绽媒、執(zhí)行器把此操作寫入 bin log ,并且把 bin log 寫入磁盤免猾;
9是辕、最后執(zhí)行器調(diào)用引擎的提交事務接口,引擎把 redo log 的狀態(tài)改 commit 猎提,至此整個更新操作完成获三。
30. 缺頁了怎么辦,物理內(nèi)存如何分配的
在第一次訪問已分配的虛擬地址空間的時候锨苏,發(fā)生缺頁中斷疙教,操作系統(tǒng)負責分配物理內(nèi)存,然后建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系伞租。
當一個進程發(fā)生缺頁中斷的時候贞谓,進程會陷入內(nèi)核態(tài),執(zhí)行以下操作:
1葵诈、檢查要訪問的虛擬地址是否合法
2裸弦、查找/分配一個物理頁
3、填充物理頁內(nèi)容(讀取磁盤作喘,或者直接置0理疙,或者啥也不干)
4、建立映射關(guān)系(虛擬地址到物理地址)
31. 虛擬內(nèi)存和物理內(nèi)存泞坦,為什么
進程開始要訪問一個地址窖贤,它可能會經(jīng)歷下面的過程:
1、每次我要訪問地址空間上的某一個地址暇矫,都需要把地址翻譯為實際物理內(nèi)存地址主之;
2择吊、所有進程共享這整一塊物理內(nèi)存李根,每個進程只把自己目前需要的虛擬地址空間映射到物理內(nèi)存上;
3几睛、進程需要知道哪些地址空間上的數(shù)據(jù)在物理內(nèi)存上房轿,哪些不在(可能這部分存儲在磁盤上),還有在物理內(nèi)存上的哪里所森,這就需要通過頁表來記錄囱持;
4、頁表的每一個表項分兩部分焕济,第一部分記錄此頁是否在物理內(nèi)存上纷妆,第二部分記錄物理內(nèi)存頁的地址(如果在的話);
5晴弃、當進程訪問某個虛擬地址的時候掩幢,就會先去看頁表逊拍,如果發(fā)現(xiàn)對應的數(shù)據(jù)不在物理內(nèi)存上,就會發(fā)生缺頁異常际邻;
6芯丧、缺頁異常的處理過程,操作系統(tǒng)立即阻塞該進程世曾,并將硬盤里對應的頁換入內(nèi)存缨恒,然后使該進程就緒,如果內(nèi)存已經(jīng)滿了轮听,沒有空地方了,那就找一個頁覆蓋骗露,至于具體覆蓋的哪個頁,就需要看操作系統(tǒng)的頁面置換算法是怎么設計的了血巍。
32.http1.x的新特性
- Http1.1 提出了長連接椒袍,HTTP 可以在一次TCP中不斷的發(fā)送請求
- Http1.1 支持先發(fā)送header,判斷是否連接成功在發(fā)送body,節(jié)約帶寬,post就是這樣做的藻茂。
- Http1.1 支持多個host
Http 2.0 支持多路復用驹暑,同一個連接可以并發(fā)處理多個請求。
Http 2.0 支持服務端推送辨赐,在返回數(shù)據(jù)之外支持額外的推送优俘。
Http 2。0 壓縮了請求頭掀序;
33. 長連接和短連接帆焕,什么時候會出現(xiàn)
長連接多用于操作頻繁,點對點的通訊不恭,而且連接數(shù)不能太多情況叶雹。每個TCP連接都需要三步握手,這需要時間换吧,如果每個操作都是先連接折晦,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開沾瓦,次處理時直接發(fā)送數(shù)據(jù)包就OK了满着,不用建立TCP連接。例如:數(shù)據(jù)庫的連接用長連接贯莺, 如果用短連接頻繁的通信會造成socket錯誤风喇,而且頻繁的socket 創(chuàng)建也是對資源的浪費。
而像WEB網(wǎng)站的http服務一般都用短鏈接缕探,因為長連接對于服務端來說會耗費一定的資源魂莫,而像WEB網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接爹耗,而且同時有成千上萬的用戶耙考,如果每個用戶都占用一個連接的話秽誊,那可想而知吧。所以并發(fā)量大琳骡,但每個用戶無需頻繁操作情況下需用短連好
34. 長連接是如何維持的锅论,心跳機制,如果一直想要連接著怎么辦
連接→數(shù)據(jù)傳輸→保持連接(心跳)→數(shù)據(jù)傳輸→保持連接(心跳)→……→關(guān)閉連接楣号;
通常的做法是最易,在服務器的程序中加入一個死循環(huán),在循環(huán)中監(jiān)測數(shù)據(jù)的變動炫狱。當發(fā)現(xiàn)新數(shù)據(jù)時藻懒,立即將其輸出給瀏覽器并斷開連接,瀏覽器在收到數(shù)據(jù)后视译,再次發(fā)起請求以進入下一個周期嬉荆,這就是常說的長輪詢(long-polling)方式
35. 靜態(tài)多態(tài)和動態(tài)多態(tài)
Java實現(xiàn)多態(tài)有三個必要條件:繼承、重寫酷含、向上轉(zhuǎn)型鄙早。
繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類。
重寫:子類對父類中某些方法進行重新定義椅亚,在調(diào)用這些方法時就會調(diào)用子類的方法限番。
向上轉(zhuǎn)型:在多態(tài)中需要將子類的引用賦給父類對象,只有這樣該引用才能夠具備技能調(diào)用父類的方法和子類的方法
編輯時多態(tài)是靜態(tài)的呀舔,主要是指方法的重載弥虐,它是根據(jù)參數(shù)列表的不同來區(qū)分不同的函數(shù),通過編輯之后會變成兩個不同的函數(shù)媚赖,在運行時談不上多態(tài)霜瘪。而運行時多態(tài)是動態(tài)的,它是通過動態(tài)綁定來實現(xiàn)的惧磺,也就是我們所說的多態(tài)性颖对。
重載和覆蓋(重寫)
36. 死鎖是什么,死鎖發(fā)生了怎么辦
死鎖豺妓,死鎖的特點
死鎖產(chǎn)生的原因惜互?
- 資源競爭
產(chǎn)生死鎖資源布讹,這里的資源是不可剝奪資源
產(chǎn)生死鎖中的競爭資源另外一種資源指的是競爭臨時資源(臨時資源包括硬件中斷琳拭、信號、消息描验、緩沖區(qū)內(nèi)的消息)
- 進程間的推進順序非法
若P1保持了資源R1,P2保持了資源R2白嘁,系統(tǒng)處于不安全狀態(tài),因為這兩個進程再向前推進膘流,便可能發(fā)生死鎖
P1 請求 R2, P2 請求 R1
死鎖產(chǎn)生的必要條件絮缅?
- 互斥鲁沥,進程對資源使用互斥
- 占有并等待,—個進程應占有至少一個資源耕魄,并等待另一個資源画恰,而該資源為其他進程所占有。
- 非搶占吸奴,資源不能被搶占允扇,只能完成任務后釋放
- 循環(huán)等待,有一組等待進程 {P0则奥,P1考润,…,Pn}读处,P0 等待的資源為 P1 占有糊治,P1 等待的資源為 P2 占有,……罚舱,Pn-1 等待的資源為 Pn 占有井辜,Pn 等待的資源為 P0 占有。
四個條件必須同時成立才會出現(xiàn)死鎖
解決死鎖的方法管闷?
- 破壞請求條件抑胎,資源一次性分配
- 破壞保持條件,只要有一個資源無法分配渐北,就不給改進程分配資源
- 破壞不可剝奪條件阿逃,當某進程獲得了部分資源,但得不到其它資源赃蛛,則釋放已占有的資源
- 破壞圈等恃锉,系統(tǒng)給每類資源賦予一個編號,每一個進程按編號遞增的順序請求資源呕臂,釋放則相反
例如:進程PA破托,使用資源的順序是R1,R2;
進程PB,使用資源的順序是R2稠集,R1厕吉;
若采用動態(tài)分配有可能形成環(huán)路條件,造成死鎖记罚。
采用有序資源分配法:R1的編號為1,R2的編號為2;
PA:申請次序應是:R1序臂,R2
PB:申請次序應是:R1,R2
這樣就破壞了環(huán)路條件实束,避免了死鎖的發(fā)生
避免死鎖的方法奥秆?
銀行家算法:首先需要定義狀態(tài)和安全狀態(tài)的概念逊彭。系統(tǒng)的狀態(tài)是當前給進程分配的資源情況。因此构订,狀態(tài)包含兩個向量Resource(系統(tǒng)中每種資源的總量)和Available(未分配給進程的每種資源的總量)及兩個矩陣Claim(表示進程對資源的需求)和Allocation(表示當前分配給進程的資源)侮叮。安全狀態(tài)是指至少有一個資源分配序列不會導致死鎖。當進程請求一組資源時悼瘾,假設同意該請求签赃,從而改變了系統(tǒng)的狀態(tài),然后確定其結(jié)果是否還處于安全狀態(tài)分尸。如果是锦聊,同意這個請求;如果不是箩绍,阻塞該進程知道同意該請求后系統(tǒng)狀態(tài)仍然是安全的孔庭。
37. 什么叫字節(jié)流,什么叫數(shù)據(jù)報
字節(jié)就是散亂的數(shù)據(jù) 報文就是添加了標記材蛛,封裝后的數(shù)據(jù)
38. 裝箱類型的緩存機制圆到?
byte,short,long,int 緩存范圍是 -128~127 char 0~127 ,boolean 是全部緩存, float和double 沒有緩存
當基本數(shù)據(jù)類型 和 封裝數(shù)據(jù)類型 進行 == + 卑吭, - 芽淡, * ,/ 會將封裝類型進行拆箱
int 4 字節(jié)豆赏,byte 1 字節(jié)挣菲, char 2 字節(jié),long 8 字節(jié)掷邦,float 4 字節(jié)
39.mybatis的$和#有什么區(qū)別白胀?
- $ 是字符串替換, # 是預編譯處理
- mybatis 在處理 # 時會將# 替換為 抚岗?或杠,調(diào)用prepareStatement的set方法進行處理
- $ 將其直接替換為字符串
-
可以防止SQL注入
40.Spring的@Autowired、@Resource分別有什么作用宣蔚?內(nèi)部如何實現(xiàn)的向抢?
@Resource 是按名字進行注入的, @Autowired 是按照類型進行注入的
- 為開啟了注解注入胚委,在Spring容器啟動時挟鸠,默認會向BeanFactory注冊AutowiredAnnotationBeanPostProcessor后置處理器,也就是在Bean實例化完后篷扩,用來做依賴注入工作的
- 找到需要注入的成員
- 對成員元素進行循環(huán)注入
- 實例化需要注入的依賴bean
- 按類型找對應的bean
- 如果找到的bean大于1個兄猩,就判斷其上面有沒有Primary注解
- 通過依賴進行注入
@Resource
依賴注入的處理類是CommonAnnotationBeanPostProcessor
解析bean-》保存beanDefition到IOC容器-》根據(jù)beanDefition實例化-》根據(jù)BeanpostProcessor依賴注入
1.Autowired是Spring提供的,Resouce是JDK提供的鉴未。
2.Autowired通過AutowiredAnnotationBeanPostProcessor實現(xiàn)屬性的依賴注入枢冤,Resouce通過CommonAnnotationBeanPostProcessor。實現(xiàn)屬性的依賴注入铜秆。
3.注解方式實例化的bean淹真,默認都是單例,沒找到定義bean Scope的入口连茧。
4.Autowired注解嚴格來說核蘸,只是按類型來注入的。因為如果按類型找不到依賴的bean啸驯,直接拋異常了客扎。配置了多個類型的bean時,會返回指定@Primary注解的bean罚斗。
5.Resouce注解徙鱼,當么有指定name時,是按類型注入的针姿;指定了name袱吆,才按name。當然前提時距淫,我還沒弄明白jndiFactory是怎么樣用的绞绒。
41.什么時候MinorGC,什么時候FullGC榕暇?
當 Edan 區(qū)內(nèi)存不夠就會觸發(fā)蓬衡,MinorGC
Full GC觸發(fā)條件:
(1)調(diào)用System.gc時,系統(tǒng)建議執(zhí)行Full GC彤枢,但是不必然執(zhí)行
(2)老年代空間不足
(3)方法去空間不足
(4)通過Minor GC后進入老年代的平均大小大于老年代的可用內(nèi)存
(5)由Eden區(qū)撤蟆、From Space區(qū)向To Space區(qū)復制時,對象大小大于To Space可用內(nèi)存堂污,則把該對象轉(zhuǎn)存到老年代家肯,且老年代的可用內(nèi)存小于該對象大小
42.有哪些垃圾收集器?都是什么作用盟猖?都針對什么區(qū)讨衣?
老年代, cms 多線程標記清除算法式镐, parallel old 多線程標記整理反镇, serial old 單線程 標記整理;
新生代娘汞,ParNew 多線程復制算法歹茶,serial 復制算法, parallel scavenge 多線程復制算法
43.Linux的常見命令知道多少?
free
df -h
ps aux | grep
tail -f
more
cat
tar -cvf
tar -zxvf
top
44.Exception有哪些惊豺?Exception的分類燎孟?
Exception分為兩類:非運行是異常和運行時異常。
java編譯器要求方法必須聲明拋出可能發(fā)生的非運行時異常尸昧,但是并不要求必須聲明拋出未被捕獲的運行時異
RuntimeException 如:NullPointerException揩页、ClassCastException;一個是檢查異常 CheckedException烹俗,如 I/O 錯誤導致的 IOException爆侣、SQLException
檢查異常 CheckedException:一般是外部錯誤,這種異常都發(fā)生在編譯階段幢妄,Java 編譯器會強 制程序去捕獲此類異常兔仰,即會出現(xiàn)要求你把這段可能出現(xiàn)異常的程序進行 try catch,該類異常一 般包括幾個方面:
- 試圖在文件尾部讀取數(shù)據(jù) 2. 試圖打開一個錯誤格式的URL 3. 試圖根據(jù)給定的字符串查找class對象蕉鸳,而這個字符串表示的類并不存在
45. java 單利實現(xiàn)雙重校驗鎖
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 第一次 singleton 判斷空
在同步代碼塊外進行判斷乎赴,避免進入同步代碼塊,提高效率
- 第二次 singeton 判斷空
如果 A 判空置吓,準備進入代碼塊无虚, 此時B拿到了時間片,進入同步代碼塊衍锚,并創(chuàng)建實例友题,A又獲得時間片進入代碼塊,創(chuàng)建實例
- 使用 volatile 作用
禁止指令重排序戴质,保證不會得到部分對象度宦;
即還沒創(chuàng)建完,另一個線程就在調(diào)用獲得告匠;
對變量的寫操作一定在讀操作之前戈抄;
46. Spring DI 是什么如何實現(xiàn)?
DI大概是這樣的后专,根據(jù)我們要獲取的BeanName,去IOC容器中找到對應的class,然后實例化出一個代理類對象划鸽,然后給這個對象的屬性賦值。
- 獲取bean 的name,如果是別名將其轉(zhuǎn)換
- 從緩存中取得單利bean
- 緩存中沒有單利bean戚哎,判斷是否可以在當前BeanFactory中獲取單利bean,否則委托當前容器的父容器去尋找裸诽,按名字和類型
- 沒有的話,創(chuàng)建bean
3.1 判斷是不是原型實例型凳,如果是丈冬,則拋出創(chuàng)建失敗異常,如果不是甘畅,下一步埂蕊。
3.2 檢查 BeanDefinition 是否在當前的容器中往弓,如果不在那可能在父類容器中,所以委托父類容器查找蓄氧,如果還沒有函似,則再上一級容器...遞歸查找。
3.3 檢查這個實例是否是為了類型檢查而獲取匀们,而不是用來使用缴淋,如果是准给,標記這個bean已經(jīng)被創(chuàng)建泄朴,如果不是,下一步露氮。
3.4 根據(jù) beanName獲取 父類的BeanDefinition祖灰,并檢查該對象類類型,比如不能是抽象類等畔规。
3.5 根據(jù) beanName獲取所有該 bean依賴的 Bean集合局扶,如果該集合有值,則遍歷DI(遞歸調(diào)用 getBean())該 bean集合里的bean叁扫,并把bean注冊給當前的bean(維護了一個 map來存放關(guān)系)三妈。
3.6 如果3.4中獲取的 BeanDefinition是單例,則根據(jù)該單例對象和 beanName和 args創(chuàng)建一個實例對象莫绣;否則畴蒲,判斷 BeanDefinition是否是原型,如果是則根據(jù) beanName,該對象, args創(chuàng)建一個實例对室;否則拿到3.4獲取的 BeanDefinition對象的生命周期 Scope,然后根據(jù) scope來創(chuàng)建實例對象模燥,參數(shù) (beanName,bd,args)。
java 程序運行的整個過程
java 原文件通過編譯器編譯成.class字節(jié)碼文件掩宜,字節(jié)碼文件通過 JVM 虛擬機蔫骂,生成機器碼文件
- 代碼編譯
- 類加載,雙親委派避免重復加載辽旋,加載,驗證檐迟,準備(準備會對一些常量進行初始化补胚,遍歷初始化為0或null),解析,初始化
- jVM 編譯 生成字節(jié)碼文件
- 將字符讀入寄存器锅减,再把它放入到存儲器中
- main 指令將“Hello World\n” 字符串中的字節(jié)從主存復制到寄存器文件糖儡,再從寄存器文件中復制到顯示設備,最終顯示在屏幕上怔匣。
java hello word運行的整個過程握联;
- 編寫好的java源文件桦沉,先通過解釋器,編譯成.class 的字節(jié)碼文件金闽;
- 然后再通過jvm的類加載器進行加載纯露,加載時采用的是雙親委派機制,加載的過程為連接代芜,驗證埠褪,準備,解析挤庇,初始化钞速;
- 在準備時 String s 會先初始化為null, 然后初始化階段,賦值為嫡秕,“hello word”;
- 當然渴语,
cpu 占用率
cpu 占用率,不就是運行占用的時間/ 總時間
操作系統(tǒng)用戶態(tài)和內(nèi)核態(tài)
內(nèi)核態(tài)就是cpu可以訪問所有數(shù)據(jù)昆咽,包括外圍設備驾凶,硬盤,網(wǎng)卡掷酗。cpu將自己從一個程序切換另一個程序调违。
用戶態(tài),只能訪問內(nèi)存泻轰,不允許訪問外圍設備技肩。占用cpu內(nèi)力被剝奪,cpu可以被其他程序獲取糕殉。
為什么要有用戶態(tài)和內(nèi)核態(tài)
由于需要限制不同的程序之間的訪問能力, 防止他們獲取別的程序的內(nèi)存數(shù)據(jù), 或者獲取外圍設備的數(shù)據(jù), 并發(fā)送到網(wǎng)絡, CPU劃分出兩個權(quán)限等級 -- 用戶態(tài) 和 內(nèi)核態(tài)
所有用戶程序都是運行在用戶態(tài)的, 但是有時候程序確實需要做一些內(nèi)核態(tài)的事情, 例如從硬盤讀取數(shù)據(jù), 或者從鍵盤獲取輸入等. 而唯一可以做這些事情的就是操作系統(tǒng), 所以此時程序就需要先操作系統(tǒng)請求以程序的名義來執(zhí)行這些操作.
工作流程如下:
- 用戶態(tài)程序?qū)⒁恍?shù)據(jù)值放在寄存器中, 或者使用參數(shù)創(chuàng)建一個堆棧(stack frame), 以此表明需要操作系統(tǒng)提供的服務.
- 用戶態(tài)程序執(zhí)行陷阱指令
- CPU切換到內(nèi)核態(tài), 并跳到位于內(nèi)存指定位置的指令, 這些指令是操作系統(tǒng)的一部分, 他們具有內(nèi)存保護, 不可被用戶態(tài)程序訪問
- 這些指令稱之為陷阱(trap)或者系統(tǒng)調(diào)用處理器(system call handler). 他們會讀取程序放入內(nèi)存的數(shù)據(jù)參數(shù), 并執(zhí)行程序請求的服務
- 系統(tǒng)調(diào)用完成后,操作系統(tǒng)會重置CPU為用戶態(tài)并返回系統(tǒng)調(diào)用的結(jié)果
websocket了解多少亩鬼?瀏覽器要向一個客戶端WebSocket連接,需要經(jīng)過哪些協(xié)議和報文阿蝶?
websocket 是h5 提供的一種瀏覽器和服務器進行的全雙工的網(wǎng)絡通信技術(shù)雳锋,屬于應用層。他是基于TCP, 復用HTTP握手通道羡洁。
Websocket 的優(yōu)點是 支持雙向通信玷过,實時性更強,更好的二進制支持筑煮,可以不攜帶完整的數(shù)據(jù)包頭辛蚊。
WebSocket復用了HTTP的握手通道。具體指的是真仲,客戶端通過HTTP請求與WebSocket服務端協(xié)商升級協(xié)議袋马。協(xié)議升級完成后,后續(xù)的數(shù)據(jù)交換則遵照WebSocket的協(xié)議秸应。
在HTTP的請求首部添加虑凛,
Connection: Upgrade
Upgrade: websocket
服務端返回內(nèi)容如下碑宴,狀態(tài)代碼101表示協(xié)議切換
WebSocket的每條消息可能被切分成多個數(shù)據(jù)幀。當WebSocket的接收方收到一個數(shù)據(jù)幀時桑谍,會根據(jù)FIN的值來判斷延柠,是否已經(jīng)收到消息的最后一個數(shù)據(jù)幀。
FIN=1表示當前數(shù)據(jù)幀為消息的最后一個數(shù)據(jù)幀锣披,此時接收方已經(jīng)收到完整的消息贞间,可以對消息進行處理。FIN=0雹仿,則接收方還需要繼續(xù)監(jiān)聽接收其余的數(shù)據(jù)幀增热。
Java線程與Linux內(nèi)核線程的映射關(guān)系
JVM線程跟內(nèi)核輕量級進程有一一對應的關(guān)系。線程的調(diào)度完全交給了操作系統(tǒng)內(nèi)核盅粪,當然jvm還保留一些策略足以影響到其內(nèi)部的線程調(diào)度钓葫,舉個例子悄蕾,在linux下票顾,只要一個Thread.run就會調(diào)用一個fork產(chǎn)生一個線程。
Java中線程的本質(zhì)帆调,其實就是操作系統(tǒng)中的線程奠骄,Linux下是基于pthread庫實現(xiàn)的輕量級進程
虛擬機中的線程狀態(tài),不反應任何操作系統(tǒng)線程狀態(tài)
HashMap 中比較的都
如果當前節(jié)點的哈希值番刊、鍵和要添加的都一致
- tranisent 是做什么用的含鳞?
Java中對象的序列化指的是將對象轉(zhuǎn)換成以字節(jié)序列的形式來表示,這些字節(jié)序列包含了對象的數(shù)據(jù)和信息芹务,一個序列化后的對象可以被寫到數(shù)據(jù)庫或文件中蝉绷,也可用于網(wǎng)絡傳輸,一般當我們使用緩存cache(內(nèi)存空間不夠有可能會本地存儲到硬盤)或遠程調(diào)用rpc(網(wǎng)絡傳輸)的時候枣抱,經(jīng)常需要讓我們的實體類實現(xiàn)Serializable接口熔吗,目的就是為了讓其可序列化。
Java中transient關(guān)鍵字的作用佳晶,簡單地說桅狠,就是讓某些被修飾的成員屬性變量不被序列化
Java中transient關(guān)鍵字的作用,簡單地說轿秧,就是讓某些被修飾的成員屬性變量不被序列化
- ClassNotFoundException 和 NotClassDefFoundError 區(qū)別中跌?
ClassNotFoundException是一個運行時異常。從類繼承層次上來看菇篡,ClassNotFoundException是從Exception繼承的漩符,所以ClassNotFoundException是一個檢查異常。
當JVM在加載一個類的時候驱还,如果這個類在編譯時是可用的嗜暴,但是在運行時找不到這個類的定義的時候津滞,JVM就會拋出一個NoClassDefFoundError錯誤。
當動態(tài)加載Class的時候找不到類會拋出該異常
當編譯成功以后執(zhí)行過程中Class找不到導致拋出該錯誤
當發(fā)生由于缺少jar文件灼伤,或者jar文件沒有添加到classpath触徐,或者jar的文件名發(fā)生變更會導致java.lang.NoClassDefFoundError的錯誤。
當類不在classpath中時狐赡,這種情況很難確切的知道撞鹉,但如果在程序中打印出System.getproperty(“java.classpath”),可以得到程序?qū)嶋H運行的classpath
運行時明確指定你認為程序能正常運行的 -classpath 參數(shù)颖侄,如果增加之后程序能正常運行鸟雏,說明原來程序的classpath被其他人覆蓋了。
NoClassDefFoundError也可能由于類的靜態(tài)初始化模塊錯誤導致览祖,當你的類執(zhí)行一些靜態(tài)初始化模塊操作孝鹊,如果初始化模塊拋出異常,哪些依賴這個類的其他類會拋出NoClassDefFoundError的錯誤展蒂。如果你查看程序日志又活,會發(fā)現(xiàn)一些java.lang.ExceptionInInitializerError的錯誤日志,ExceptionInInitializerError的錯誤會導致java.lang.NoClassDefFoundError: Could not initialize class锰悼。
- jdk 的命令行工具 柳骄?
jps 虛擬機進程工具,
jstack 用于生成虛擬機當前時刻的線程快照
jinfo 作用是實時地查看和調(diào)整虛擬機各項參數(shù)
jstat(JVM statistics Monitoring)是用于監(jiān)視虛擬機運行時狀態(tài)信息的命令,它可以顯示出虛擬機進程中的類裝載箕般、內(nèi)存耐薯、垃圾收集哮塞、JIT編譯等運行數(shù)據(jù)
jstack 尋找java 的死鎖
- 用什么查詢工具對 java 程序來判斷是死鎖补箍?
jstack
- utf-8是怎么做的?
英語字符與二進制位之間的關(guān)系雌隅,做了統(tǒng)一規(guī)定杯聚。這被稱為 ASCII 碼;
大寫的字母A是65(二進制01000001)
簡體中文常見的編碼方式是 GB2312臼婆,使用兩個字節(jié)表示一個漢字,所以理論上最多可以表示 256 x 256 = 65536 個符號械媒。
每一個符號都給予一個獨一無二的編碼,就是 Unicode.
UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實現(xiàn)方式.
UTF-8 最大的一個特點目锭,就是它是一種變長的編碼方式。它可以使用1~4個字節(jié)表示一個符號纷捞,根據(jù)不同的符號而變化字節(jié)長度
- 對一個類里面有數(shù)據(jù)庫連接痢虹,怎么對這個類加鎖?
在Java程序運行時環(huán)境中主儡,JVM需要對兩類線程共享的數(shù)據(jù)進行協(xié)調(diào):
1)保存在堆中的實例變量
2)保存在方法區(qū)中的類變量
- 怎么java實現(xiàn)多線程對資源安全訪問的方法奖唯?
- wait()/notify()方法
- await()/signal()方法
- BlockingQueue阻塞隊列方法
- 除了MVC 你還知道什么架構(gòu)?
被廣泛使用的MVVM模式,還有MVP模式, 設計模式糜值;
- 你一般用什么設計模式丰捷?
工廠坯墨,觀察者, - 如果對一個類內(nèi)的資源實現(xiàn)不同的操作訪問病往,使用什么設計模式捣染?
策略模式定義
策略模式(Strategy Pattern),將各種算法封裝到具體的類中停巷,作為一個抽象策略類的子類耍攘,使得它們可以互換∨锨冢客戶端可以自行決定使用哪種算法蕾各。
- CAP,ACID,兩階段提交協(xié)議,分布式事務介紹一下庆揪?
分布式事務是指事務的參與者式曲、支持事務的服務器、資源服務器以及事務管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點之上缸榛。
- 一個資源備份三臺機器吝羞,如何對其進行增刪操作,設計一下仔掸;
- 多線程求出1萬一下的所有素數(shù)脆贵?
- 統(tǒng)計一個文件里面單詞的數(shù)量?
- 類加載過程起暮?
- redis 的持久化?
- redis 的機器怎么實現(xiàn)的会烙?
- 程序遇見問題你一般怎么解決的负懦?
- 運行時多態(tài)說下,舉個例子柏腻?
- 求函數(shù)的極值怎么求纸厉?
- 統(tǒng)計一個文件下,迭代的 java 源代碼的行數(shù)
find / -name *.java | wc -l
遍歷此區(qū)間的int五嫂,塞進數(shù)組或集合颗品。
然后循環(huán)套進x^2+2中,得出的結(jié)果塞進新的數(shù)組或集合沃缘。
求出這個新數(shù)組或集合的最值即可
java 的 HelloWorld 程序的整個過程躯枢;
java 原文件通過編譯器編譯成.class字節(jié)碼文件,字節(jié)碼文件通過 JVM 虛擬機槐臀,生成機器碼文件
代碼編譯 锄蹂,詞法語法語義分析,將java 原代碼編譯成字節(jié)碼文件水慨;
類加載機制得糜,采用雙親委派避免重復加載(類名+類加載器)敬扛,加載,驗證朝抖,準備(準備會對一些常量進行初始化啥箭,遍歷初始化為0或null),解析,初始化
String s = "hellowold";在jvm內(nèi)存中棧和本地線程棧是線程私有的治宣,會在線程中創(chuàng)建一個main方法的棧幀捉蚤,里面s存放在其中的字符變量表中,然后“helloword”是一個字符串常量炼七,在jvm中會存放在方法區(qū)中的字符常量池中的缆巧,在棧中 s 變量, 去指向它豌拙,如果 這個 new String("helloword"), 先指向堆空間陕悬,對空間再去指向 方法區(qū)常量池中。方法區(qū)還存放對象的元數(shù)據(jù)按傅。
System.out.println(s):系統(tǒng)加載System.class字節(jié)碼文件到方法區(qū)捉超,并且系統(tǒng)會默認在堆區(qū)創(chuàng)建System.out、System.in唯绍、System.err三個對象拼岳。
字符串在被輸出時會自動調(diào)用toString()方法惜纸。JVM 字節(jié)碼執(zhí)行引擎 生成機器節(jié)碼文件绝骚,執(zhí)行系統(tǒng)找到Main方法為其分配cpu進行執(zhí)行压汪;
cpu的執(zhí)行分為取值粪牲,譯碼止剖,執(zhí)行
操作系統(tǒng)開始執(zhí)行指令失敗亭引,缺中斷發(fā)送痛侍;
操作系統(tǒng)分配一頁內(nèi)存主届,將代碼從磁盤讀入枫夺,繼續(xù)執(zhí)行
程序執(zhí)行系統(tǒng)調(diào)用橡庞,在文件描述符中寫一字符串
操作系統(tǒng)檢查字符串的位置是否正確
操作系統(tǒng)找到字符串被送往的設備
設備是一個偽終端,又一個進程控制
操作系統(tǒng)將字符串送給該進程
該進程告訴窗口系統(tǒng)它要顯示字符串
窗口系統(tǒng)確定這是一個合法的操作吧趣,然后將字符串轉(zhuǎn)成像素
視頻硬件將成像素表示轉(zhuǎn)換成一組模擬信號控制顯示器在(重畫屏幕)
顯示器發(fā)射電子束强挫,你在屏幕上看到“hello world”
jstack 堆棧跟蹤工具,jps 進程狀態(tài)八匠,javap -v 字節(jié)碼反編譯
通常設置成跟最大堆內(nèi)存一樣,減少GC
jvm 參數(shù),-Xmx 最大堆內(nèi)存,-Xms 最小堆內(nèi)存
-Xmn 年輕代大小 -Xss 最大椛麒担空間
-XX:MetaspaceSize
緩存一致性 64k
重量級總線鎖
MESI, Share modifiy exculsive invalid
S S M S E I S S
嗅探到其他cpu 緩存對該值操作的狀態(tài)
- 線程對共享變量的可見性?
第一個條件就是不能是自增自減等操作岁疼,上文已經(jīng)提到volatile不保證原子性
兩個變量值相互約束瑰排,也不能使用volatile
- 如何控制線程的執(zhí)行順序椭住?
通過 join 方法,保證多線程順序葫掉。join讓主線程等待子線程結(jié)束繼續(xù)執(zhí)行俭厚。
join 里面就是調(diào)用 wait 方法套腹,讓主線程(Main)等待幢码,直到thread1 執(zhí)行完,控制多線程的順序性贞铣。
ExecutorService pool = Executors.newSingleThreadExcutor();
他里面就是一個隊列,只有一個線程酱畅,也會按順序執(zhí)行。
- JMM 可見性餐蔬,原子性仗考,有序性
緩存一致性
線程之間如何通信? 線程之間如何同步痪寻?
消息通信 wait notifiy
java 通信是對程序員隱式,共享內(nèi)存
分布式鎖
- 數(shù)據(jù)庫方式,創(chuàng)建唯一約束研侣, 可重入 ,id
- zookeeper 末誓,數(shù)據(jù)結(jié)構(gòu),樹型結(jié)構(gòu)
- redis setnx 為key 不存在設置值
修改值傳遞,需要通過反射來進行互轉(zhuǎn)
integer 在 -128 到 127 有內(nèi)存緩存
解決方案 主動 new 來避免 intergerCache緩存
java 使用的是內(nèi)核線程模型窜醉;
線程在線程池中就是一直被阻塞著拜英,保存線程虫给;
如果隊列中沒有任務時抹估,核心線程會一直阻塞在獲取任務的方法瓷式,直到返回任務。
1. 講講你們項目的啟動過程
首先,我們項目是ssm框架妒挎。
- 創(chuàng)建一個servletContext 容器,將我們 Rootconfig保存到容器中庸队;
- 創(chuàng)建一個contextLoaderListener, 注冊到 servletContext中;
- 創(chuàng)建一個空的子容器,將webConfig,保存到中煌贴,setParent(servletContext),將servletContext作為父容器;
- 創(chuàng)建一個dispatcherServlet,并將其注冊到子容器中
- contextLoaderListener笙各,和 dispatcherServlet會進行刷新容器,將bean加載到我們?nèi)萜髦校?/li>
bean刷新過程
- 刷新容器惶楼,標記容器啟動
- 獲取子類的BeanFactory
- 對BeanFactory進行屬性填充
- 調(diào)用BeanFactoryPostProcessor 進行擴展修改屬性
- 調(diào)用BeanPostProcessor 修改bean創(chuàng)建實例
- 創(chuàng)建事件廣播
- 刷新,廣播
分布式鎖需要考慮什么因素?
分布式鎖可以通過 zookeeper , redis , mysql 來實現(xiàn)
synchronized , lock 都是對線程的加鎖颂翼,不同進程加鎖,需要通過1.外邊存儲狀態(tài),2. 全局唯一標識刽锤,3. 至少兩種狀態(tài)
如何提升系統(tǒng)的QPS(每秒查詢率)和吞吐量
- 如果我們系統(tǒng)單節(jié)點,我們可以通過多節(jié)點+負載均衡,nginx,tomcat
- 數(shù)據(jù)庫输涕,可以增加緩存,系統(tǒng)拆分瞳收,異步MQ
- 應用層 CDN:依靠網(wǎng)絡中的各個節(jié)點谐宙,就近發(fā)放靜態(tài)資源
BIO, NIO搭综,AIO 總結(jié)
IO 就是讀取的文件是存儲在磁盤上的,我們的目的是把它讀取到內(nèi)存中√糜停可以把這個步驟簡化成把數(shù)據(jù)從硬件(硬盤)中讀取到用戶空間中。
BIO 同步阻塞I/O模式,數(shù)據(jù)的讀取寫入必須阻塞在一個線程內(nèi)等待其完成.
BIO 通信模型 的服務端系宜,通常由一個獨立的 Acceptor 線程負責監(jiān)聽客戶端的連接欠母。我們一般通過在while(true) 循環(huán)中服務端會調(diào)用 accept() 方法等待接收客戶端的連接的方式監(jiān)聽請求.
NIO 它支持面向緩沖的踩寇,基于通道的I/O操作方法辣卒。
AIO 異步 IO 是基于事件和回調(diào)機制實現(xiàn)的,也就是應用操作之后會直接返回,不會堵塞在那里咧欣,當后臺處理完成,操作系統(tǒng)會通知相應的線程進行后續(xù)的操作。
操作系統(tǒng)的運行機制和體系結(jié)構(gòu)
當線程陷入內(nèi)核態(tài)就可以執(zhí)行特權(quán)指令和非特權(quán)指令,在用戶態(tài)只能執(zhí)行非特權(quán)指令囤躁。
RPC 和 RestFul 的理解?
RPC 是遠程過程調(diào)用,像本地方法一樣調(diào)用服務器方法。
RPC 分為同步和異步
同步RPC 例如webService, RMI
異步RPC 是java實現(xiàn)版JMS MQ哨鸭,kafka
主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調(diào)用的所有交換的數(shù)據(jù)都在這個連接里傳輸志群。
當A服務器上的應用發(fā)起遠程過程調(diào)用時,方法的參數(shù)需要通過底層的網(wǎng)絡協(xié)議如TCP傳遞到B服務器,由于網(wǎng)絡協(xié)議是基于二進制的,內(nèi)存中的參數(shù)的值要序列化成二進制的形式,也就是序列化(Serialize)或編組(marshal),通過尋址和傳輸將序列化的二進制發(fā)送給B服務器篙程。
REST 是一種架構(gòu)分隔触趴,通過HTTP協(xié)議爽冕,以URI對網(wǎng)絡資源進行唯一標識,響應端根據(jù)請求端的不同需求,通過無狀態(tài)通信。
無狀態(tài)通信娜搂,是指服務端(響應端)不保存任何與特定HTTP請求相關(guān)的資源,應用狀態(tài)必須由請求方在請求過程中提供
RPC 框架
1)服務提供者(Server)對外提供后臺服務,將自己的服務信息涮坐,注冊到注冊中心
2)注冊中心(Registry)用于服務端注冊遠程服務以及客戶端發(fā)現(xiàn)服務昵时。
3)服務消費者(Client) 從注冊中心獲取遠程服務的注冊信息救巷,然后進行遠程過程調(diào)用俄占。
避免多線程競爭
- 不可變對象
- 互斥鎖
- ThreadLocal 對象
- CAS;
課外喜歡讀什么書籍渤弛?
- java編程思想
- java并發(fā)編程藝術(shù)
- 深入理解java虛擬機
- 重構(gòu)現(xiàn)有代碼
- elasticsearch服務器開發(fā)
- 高性能Mysql
你有什么想問鹰贵?
我們部門對實習生是怎么培養(yǎng)的籽前?
我們部門對后臺使用的技術(shù)組件肄梨?
線程和進程的區(qū)別蓖租?
線程和進程都是對cpu工作時間段的描述
cpu在工作時會存在任務的切換齐婴。進程包括上下文切換主慰。
線程是共享了進程的上下文環(huán)境,的更為細小的CPU時間段鲫售。
進程有獨立的地址空間共螺,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響藐不,而線程只是一個進程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量秦效,但線程之間沒有單獨的地址空間雏蛮,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯阱州,但在進程切換時挑秉,耗費資源較大,效率要差一些苔货。
一個程序至少有一個進程,一個進程至少有一個線程.
一個線程可以創(chuàng)建和撤銷另一個線程;同一個進程中的多個線程之間可以并發(fā)執(zhí)行.
協(xié)程與線程主要區(qū)別是它將不再被內(nèi)核調(diào)度犀概,而是交給了程序自己而線程是將自己交給內(nèi)核調(diào)度,同時協(xié)程比線程更輕量級夜惭,多核cpu,協(xié)程不能實現(xiàn)真正并行姻灶。
進程的調(diào)度算法?
FCFS 先來先服務調(diào)度算法诈茧,既可用于作業(yè)調(diào)度产喉,也可用于進程調(diào)度。最先進入就緒隊列的先進行調(diào)度。
SJF 短作業(yè)優(yōu)先調(diào)度算法曾沈,后備隊列中選擇一個或若干個估計運行時間最短的作業(yè)这嚣,將它們調(diào)入內(nèi)存運行。
時間片輪轉(zhuǎn)法晦譬,每次調(diào)度時疤苹,把CPU分配給隊首進程,并令其執(zhí)行一個時間片敛腌。
多級反饋隊列調(diào)度算法卧土,設置多個就緒隊列,并為各個隊列賦予不同的優(yōu)先級像樊,優(yōu)先級高的時間片越小尤莺。第一隊列空閑時,調(diào)度程序才調(diào)度第二隊列中的進程運行生棍;
剝奪原則有:優(yōu)先權(quán)原則颤霎、短進程優(yōu)先原則、時間片原則涂滴。
linux 實時進程采用了兩種調(diào)度策略友酱,F(xiàn)IFO(先來先服務調(diào)度)和RR(時間片輪轉(zhuǎn)調(diào)度)。
Windows 系統(tǒng)其調(diào)度方式比較復雜柔纵,它的處理器調(diào)度的調(diào)度單位是線程而不是進程缔杉,是基于優(yōu)先級的搶占式多處理器調(diào)度
linux 下的IO復用
相同點:都使用I/O復用模型
區(qū)別:
1、支持一個進程所能打開的最大連接數(shù)不同搁料。
select最小或详,單個進程所能打開的最大連接數(shù)有FD_SETSIZE宏定義。
poll使用鏈表無最大限制郭计,
epoll有限制但很大霸琴,1g內(nèi)存支持10w個連接。
2昭伸、FD(文件描述符)劇增后的I/O效率問題梧乘。
select、poll使用遍歷模式勋乾,每次調(diào)用時都會對連接進行線性遍歷宋下,所以隨著FD的增加會造成遍歷速度慢的“線性下降性能問題”。
epoll只關(guān)注活躍的socket辑莫。因為epoll內(nèi)核中實現(xiàn)是根據(jù)每個fd上的callback函數(shù)來實現(xiàn)的学歧,只有活躍的socket才會主動調(diào)用callback。socket活躍較少的情況下沒有問題各吨,但如果所有socket都很活躍的情況下枝笨,可能會有性能問題袁铐。
3、消息傳遞方式横浑。
select 剔桨、poll 需要將數(shù)據(jù)從內(nèi)核拷貝到用戶空間。
epoll 通過內(nèi)核和用戶空間共享一塊內(nèi)存來實現(xiàn)徙融。
4洒缀、觸發(fā)模式不同
select(),poll()模型都是水平觸發(fā)模式,信號驅(qū)動IO是邊緣觸發(fā)模式欺冀。
epoll()模型即支持水平觸發(fā)树绩,也支持邊緣觸發(fā),默認是水平觸發(fā)隐轩。
總結(jié):
在選擇select饺饭,poll,epoll時要根據(jù)具體的使用場合以及這三種方式的自身特點:
1职车、表面上看epoll的性能最好瘫俊,但是在連接數(shù)少并且連接都十分活躍的情況下,select和poll的性能可能比epoll好悴灵,畢竟epoll的通知機制需要很多函數(shù)回調(diào)扛芽。
2、select低效是因為每次它都需要輪詢积瞒。但低效也是相對的胸哥,視情況而定,也可通過良好的設計改善
在Java 1.4以前赡鲜,只有一種IO模型,就是BIO(Blocking-IO庐船,阻塞IO)银酬。所以當時Java在處理高并發(fā)時性能并不好,通常使用多線程+阻塞IO來實現(xiàn)Web Server筐钟,然后使用線程池協(xié)助揩瞪。比如Tomcat就是基于這個原理。
BIO相關(guān)的類和接口就是我們在入門Java的時候通常會了解到的InputStream篓冲、OutputStream李破、Reader、Writer,這些的底層原理都是BIO
阻塞IO就是應用進程通過系統(tǒng)調(diào)用來通知內(nèi)核來準備數(shù)據(jù)壹将,數(shù)據(jù)沒有準備好久一直等待嗤攻,然后拷貝完成,返回執(zhí)行成功诽俯。
分頁和分段的區(qū)別妇菱?
- 分頁和分段都是為了管理好計算機的內(nèi)存資源。
- 為了實現(xiàn)分段的這個技術(shù),需要引入虛擬地址空間的概念闯团。分段可以解決地址空間不隔離辛臊,程序運行地址不確定。
- 分頁這個技術(shù)房交,它的虛擬地址空間仍然是連續(xù)的彻舰,但是,每一頁映射后的物理地址就不一定是連續(xù)的了候味。正是因為有了分頁的概念刃唤,程序的換入換出就可以以頁為單位了。
操作系統(tǒng)的功能负溪?
從資源管理的角度——五大基本功能
1.進程和線程的管理 ——進程線程的狀態(tài)战虏、控制、同步互斥敞映、通信調(diào)度等
2.存儲管理——分配/回收边臼、地址轉(zhuǎn)換、存儲保護等
3.文件管理——文件目錄崖堤、文件操作侍咱、磁盤空間、文件存取控制
4.設備管理——設備驅(qū)動密幔、分配回收楔脯、緩沖技術(shù)等
5.用戶接口——系統(tǒng)命令、編程接口
進程間的通信
每個進程有自己的地址空間胯甩,進程間的數(shù)據(jù)交換必須通過內(nèi)核昧廷。
進程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進程2再從內(nèi)核緩沖區(qū)把數(shù)據(jù)讀走偎箫,內(nèi)核提供的這種機制稱為進程間通信木柬。
管道,半雙工淹办,只能用于父子進程或者兄弟進程之間(具有親緣關(guān)系的進程);管道的實質(zhì)是一個內(nèi)核緩沖區(qū)眉枕,進程以先進先出的方式從緩沖區(qū)存取數(shù)據(jù),管道一端的進程順序的將數(shù)據(jù)寫入緩沖區(qū)怜森,另一端的進程則順序的讀出數(shù)據(jù)速挑。
消息隊列,消息隊列存放在內(nèi)核中副硅,只有在內(nèi)核重啟(即姥宝,操作系統(tǒng)重啟)或者顯示地刪除一個消息隊列時,該消息隊列才會被真正的刪除恐疲。消息隊列是消息的鏈表,具有特定的格式,存放在內(nèi)存中并由消息隊列標識符標識.
共享內(nèi)存(share memory)
使得多個進程可以可以直接讀寫同一塊內(nèi)存空間伶授,是最快的可用IPC形式断序。是針對其他通信機制運行效率較低而設計的。
- 信號量
信號量是一個計數(shù)器糜烹,用于多進程對共享數(shù)據(jù)的訪問违诗,信號量的意圖在于進程間同步。
- 套接字
套接字是一種通信機制疮蹦,憑借這種機制诸迟,客戶/服務器(即要進行通信的進程)系統(tǒng)的開發(fā)工作既可以在本地單機上進行,也可以跨網(wǎng)絡進行愕乎。
進程同步: 信號量阵苇,管程
線程同步: 信號量,互斥量感论,臨界區(qū)
四種進程或線程同步互斥的控制方法
1绅项、臨界區(qū):通過對多線程的串行化來訪問公共資源或一段代碼,速度快比肄,適合控制數(shù)據(jù)訪問快耿。
2、互斥量:只有擁有互斥對象的線程才具有訪問資源的權(quán)限
3芳绩、信號量:為控制一個具有有限數(shù)量用戶資源而設計掀亥。
線程之間的通信是沒有問題的:
同步主要是臨界區(qū)、互斥妥色、信號量搪花、事件
進程間通信是管道、內(nèi)存共享嘹害、消息隊列撮竿、信號量、socket
共通之處是笔呀,信號量和消息(事件)
多態(tài)
- 繼承的多態(tài)
引用子類的父類類型倚聚,在處理該引用時,它適用于繼承該父類的所有子類凿可,子類對象的不同,對方法的實現(xiàn)也就不同授账,執(zhí)行相同動作產(chǎn)生的行為也就不同枯跑。
當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法白热,但是這個被調(diào)用的方法必須是在超類中定義過的敛助,也就是說被子類覆蓋的方法,但是它仍然要根據(jù)繼承鏈中方法調(diào)用的優(yōu)先級來確認方法屋确,該優(yōu)先級為:this.show(O)纳击、super.show(O)续扔、this.show((super)O)、super.show((super)O)焕数。
常見排序算法的時間復雜度和穩(wěn)定性
冒泡纱昧、選擇、直接插入 排序需要兩個for循環(huán)堡赔,每次只關(guān)注一個元素识脆,平均時間復雜度為O(n2)O(n2)(一遍找元素O(n)O(n),一遍找位置O(n)O(n))
快速善已、歸并灼捂、希爾、堆基于分治思想换团,log以2為底悉稠,平均時間復雜度為O(nlogn)O(nlogn)(一遍找元素O(n)O(n),一遍找位置O(logn)O(logn))
排序前后相同元素的相對位置不變艘包,則稱排序算法是穩(wěn)定的的猛;
快希選堆,不穩(wěn)定辑甜,其他都穩(wěn)定衰絮。
B樹,B+樹磷醋,紅黑樹本質(zhì)區(qū)別
紅黑樹其實就是平衡樹的一種猫牡,復雜的定義和規(guī)則,最后都是為了保證樹的平衡性邓线。
因為樹的查找性能取決于樹的高度淌友,讓樹盡可能平衡,就是為了降低樹的高度骇陈。
B樹常用在文件系統(tǒng)的索引上震庭,那為什么文件索引喜歡用B樹而不是紅黑樹呢?
因為文件系統(tǒng)和數(shù)據(jù)庫的索引都是存在硬盤上的你雌,并且如果數(shù)據(jù)量大的話器联,不一定能一次性加載到內(nèi)存。
所以一棵樹都無法一次性加載進內(nèi)存婿崭,又如何談查找拨拓。所以B樹的多路存儲能力就出來了,可以每次加載B樹的一個節(jié)點氓栈,然后一步步往下找渣磷。
是為了進一步的降低樹的高度,路數(shù)越多授瘦,樹的高度就越低
所以醋界,如果實在內(nèi)存中竟宋,紅黑樹比B樹的效率更高,但涉及到磁盤操作形纺,B樹就更優(yōu)了丘侠。
B+樹是在B樹的基礎上基礎上進行改造,它的數(shù)據(jù)都在葉子節(jié)點挡篓,同時葉子節(jié)點之間還加了指針形成鏈表*
可以方便進行范圍查詢婉陷。
靜態(tài)鏈接和動態(tài)鏈接的區(qū)別?
- 靜態(tài)鏈接裝載是比較快
- 動態(tài)鏈接更節(jié)省內(nèi)存官研,減少頁面的交換秽澳。
缺點: 使用靜態(tài)鏈接生成的可執(zhí)行文件體積較大,包含相同的公共代碼戏羽,造成浪費担神;
動態(tài)鏈接庫,缺點是由于是運行時加載始花,可能會影響程序的前期執(zhí)行性能妄讯。
分頁和分段的區(qū)別?
主要區(qū)別表現(xiàn)在以下三個方面:
(1) 頁是信息的物理單位酷宵,分頁是為實現(xiàn)離散分配方式亥贸,以消減內(nèi)存的外零頭,提高內(nèi)存的利用率浇垦。段則是信息的邏輯單位炕置,它含有一組其意義相對完整的信息。分段的目的是為了能更好地滿足用戶的需要男韧。
(2) 頁的大小固定且由系統(tǒng)決定朴摊;而段的長度卻不固定,決定于用戶所編寫的程序此虑。
(3) 分頁的地址空間是一維的甚纲,程序員只需利用一個記憶符,即可表示一個地址朦前;而分段的作業(yè)地址空間是二維的介杆,程序員在標識一個地址時,既需給出段名韭寸,又需給出段內(nèi)地址
事務是如何保證原子性的春哨?
innodb 是通過undo 和 redo 來保證事務的原子性
每執(zhí)行一條對數(shù)據(jù)產(chǎn)生影響的SQL(增刪改),就會記錄與之相反的操作到undo 日志(撤銷日志)棒仍,(delete 會形成 insert, update 會記錄更新前), 一旦事務回滾臭胜,會執(zhí)行 undo 日志莫其,同時事務中的SQL會記錄到 redo, 一旦事務提交癞尚,redo 會持久化到磁盤。
為什么使用 B+ 樹乱陡?
數(shù)據(jù)庫索引在數(shù)據(jù)量大的情況下都是放在磁盤上浇揩,而磁盤IO的讀寫效率是非常慢的,矮胖的B+樹就是比較好的選擇憨颠。
B+ 樹的中間節(jié)點是不保存數(shù)據(jù)的胳徽,所以磁盤頁可以容納更多節(jié)點元素,更加的矮胖爽彤。
B 樹的查詢可以在中間節(jié)點結(jié)束养盗, B+ 樹的查詢,必須查找到葉子節(jié)點适篙,B+ 樹比較穩(wěn)定往核。
B+ 樹的范圍查詢只需要遍歷葉子節(jié)點的鏈表即可, B 樹需要重復的中序遍歷
B+ 樹的葉子節(jié)點是鏈表結(jié)構(gòu)
葉子結(jié)點本身依關(guān)鍵字的大小自小而大順序鏈接
B+ 樹允許元素重復
各種鎖的應用場景嚷节?
Java線程鎖總結(jié)
** 1.synchronized:**
在資源競爭不是很激烈的情況下聂儒,偶爾會有同步的情形下,synchronized是很合適的硫痰。原因在于衩婚,編譯程序通常會盡可能的進行優(yōu)化synchronize,另外可讀性非常好效斑。
** 2.ReentrantLock:**
在資源競爭不激烈的情形下非春,性能稍微比synchronized差點點。但是當同步非常激烈的時候鳍悠,synchronized的性能一下子能下降好幾十倍税娜,而ReentrantLock確還能維持常態(tài)。
高并發(fā)量情況下使用ReentrantLock藏研。
** 3.Atomic:**
和上面的類似敬矩,不激烈情況下,性能比synchronized略遜蠢挡,而激烈的時候弧岳,也能維持常態(tài)。激烈的時候业踏,Atomic的性能會優(yōu)于ReentrantLock一倍左右禽炬。但是其有一個缺點,就是只能同步一個值勤家,一段代碼中只能出現(xiàn)一個Atomic的變量腹尖,多于一個同步無效。因為他不能在多個Atomic之間同步伐脖。
所以热幔,我們寫同步的時候乐设,優(yōu)先考慮synchronized,如果有特殊需要绎巨,再進一步優(yōu)化近尚。ReentrantLock和Atomic如果用的不好,不僅不能提高性能场勤,還可能帶來災難戈锻。
java 鎖機制
- 樂觀鎖,悲觀鎖
- 共享鎖和媳,排它鎖
- 公平鎖格遭,非公平鎖
悲觀鎖,認為自己在使用數(shù)據(jù)的時候一定有別的線程來修改數(shù)據(jù)窗价,在獲取數(shù)據(jù)的時候會先加鎖如庭,確保數(shù)據(jù)不會被別的線程修改,具體的實現(xiàn)由Synchronized, 接口lock的實現(xiàn)類撼港。
適用的場景:寫操作較多坪它,先加鎖可以保證數(shù)據(jù)的正確性。
樂觀鎖帝牡,認為自己在使用數(shù)據(jù)時不會有其他線程來修改數(shù)據(jù)往毡,在更新數(shù)據(jù)時判斷有沒別的線程已經(jīng)更新。
實現(xiàn)有: CAS算法靶溜,AtomicInteger原子自增實現(xiàn)开瞭。
使用場景:讀操作較多,不加鎖可以提升性能罩息。
阻塞到喚醒會涉及到上下文的切換嗤详。
自適應的自旋鎖是假定不同的線程持有同一個鎖對象的時間基本相當,競爭度趨于穩(wěn)定瓷炮,可以根據(jù)上一次自旋時間調(diào)整下一次自旋時間葱色。
上下文切換,耗費資源娘香,只有內(nèi)核級線程才可以進行進程管理苍狰。
為什么線程上下文切換消耗時間?
線程棧中有程序計數(shù)器烘绽,寄存器淋昭,方法的棧幀
cpu在進行計算時計算的中間變量存儲在寄存器里。
在線程切換的過程中安接,需要將線程的中間計算結(jié)果翔忽,存儲在從寄存器中寫回到內(nèi)存線程PCB中保存現(xiàn)場,清空原有的寄存器,線程2再進行切換歇式。線程2執(zhí)行完再去喚醒線程1矢赁,需要將pcb中的中間結(jié)果寫入寄存器。
- 用戶態(tài)切換內(nèi)核態(tài)贬丛,
- 需要保存上一個線程中現(xiàn)場。
一個線程的時間片只會分配到一個核上去给涕,多個cpu核共用一套寄存器豺憔。
Synchronized 和 j.u.c.Lock 在獲取鎖的監(jiān)視器對象,和獲取state狀態(tài)的區(qū)別够庙?
Synchronied 是軟件層依賴于jvm實現(xiàn)恭应,Lock 使用cas + volatile是在硬件層,依賴cpu指令實現(xiàn)耘眨。
每一個對象都是一個監(jiān)視器鎖(monitor),當monitor被占用就處于鎖定狀態(tài)昼榛,執(zhí)行monitorenter 嘗試獲取monitor所有權(quán),兩個指令的執(zhí)行是JVM通過調(diào)用操作系統(tǒng)的互斥原語mutex來實現(xiàn)剔难。被阻塞的線程會被掛起胆屿、等待重新調(diào)度,會導致“用戶態(tài)和內(nèi)核態(tài)”兩個態(tài)之間來回切換偶宫,對性能有較大影響非迹。
java 對象頭
在JVM中,對象在內(nèi)存中的布局分為三塊區(qū)域:對象頭纯趋、實例數(shù)據(jù)和對齊填充憎兽。
對象頭:mark word 存儲對象自身的運行時數(shù)據(jù),類型指針吵冒,若為數(shù)組還應該記錄數(shù)組長度
markword 存儲hashcode,age,偏向狀態(tài)纯命,鎖狀態(tài),epoch
redis setnx 的原理
setnx key value原理是痹栖,將key設置為value,
當且僅當亿汞,key不存在,若key存在结耀,則setnx不做任何動作留夜。
其次redis 是單進程單線程模型
釋放鎖,就是將rediskey 進行刪除图甜。
為了防止碍粥,最后沒釋放鎖,可以加上過期時間黑毅。
高并發(fā)情況也會出現(xiàn)問題嚼摩,執(zhí)行時間和釋放時間不同。
當前線程加的鎖,可能被其他線程給釋放掉枕面。
解決思路愿卒,每一個線程設置一個唯一的時間戳或者唯一的id
在刪除鎖是,判斷當前value是否是自己加的鎖潮秘。
解決思路琼开,可以新開線程去檢測,key是否持有鎖枕荞,如果有延遲超時時間10s
redission ,lock(), unlock();
進程與線程的本質(zhì)區(qū)別柜候、以及各自的使用場景。
- 進程和線程都是描述cpu時間片的一種方式
- 進程是包含了上下文環(huán)境躏精,同時進程擁有獨立的地址空間
- 一個進程可以對應多個線程渣刷,他們共享進程的全部資源,虛擬地址空間矗烛,文件描述符辅柴,信號處理等,
- 通信區(qū)別是瞭吃,每一個進程有獨立的地址空間碌嘀,所有他們的通信 消息隊列,共享內(nèi)存歪架,套接字筏餐,管道,管程牡拇,線程間通信可以共享內(nèi)存通信魁瞪,主要的問題是通過鎖機制和信號量進行同步。
- 線程的上下文切換比進程上下文切換要快惠呼。
多進程適合于多機分布导俘,線程適合多核分布。
業(yè)務弱相關(guān)使用進程剔蹋,強相關(guān)使用線程旅薄。
進程的調(diào)度算法?
FCFS 先來先服務調(diào)度算法泣崩,既可用于作業(yè)調(diào)度少梁,也可用于進程調(diào)度。最先進入就緒隊列的先進行調(diào)度矫付。
SJF 短作業(yè)優(yōu)先調(diào)度算法凯沪,后備隊列中選擇一個或若干個估計運行時間最短的作業(yè),將它們調(diào)入內(nèi)存運行买优。
時間片輪轉(zhuǎn)法妨马,每次調(diào)度時挺举,把CPU分配給隊首進程,并令其執(zhí)行一個時間片烘跺。
多級反饋隊列調(diào)度算法湘纵,設置多個就緒隊列,并為各個隊列賦予不同的優(yōu)先級滤淳,優(yōu)先級高的時間片越小梧喷。第一隊列空閑時,調(diào)度程序才調(diào)度第二隊列中的進程運行脖咐;
剝奪原則有:優(yōu)先權(quán)原則伤柄、短進程優(yōu)先原則、時間片原則文搂。
linux 實時進程采用了兩種調(diào)度策略,F(xiàn)CFS(先來先服務調(diào)度)和RR(時間片輪轉(zhuǎn)調(diào)度)秤朗。
Windows 系統(tǒng)其調(diào)度方式比較復雜煤蹭,它的處理器調(diào)度的調(diào)度單位是線程而不是進程,是基于優(yōu)先級的搶占式多處理器調(diào)度
協(xié)程的作用
- 協(xié)程的本質(zhì)是用戶級線程取视,是更輕量級的硝皂。
- 協(xié)程與線程主要區(qū)別是它將不再被內(nèi)核調(diào)度,而是交給了程序自己而線程是將自己交給內(nèi)核調(diào)度,
- 協(xié)程避免反復系統(tǒng)調(diào)用,還有進程切換造成的開銷吻贿。
常見的進程同步問題
- 生產(chǎn)者消費者問題
- 讀者和寫者問題
- 哲學家就餐問題
mysql中鎖尚骄,死鎖解除
mysql 中鎖 悲觀鎖 先獲取鎖再執(zhí)行業(yè)務 select * for update
樂觀鎖,先執(zhí)行業(yè)務壤躲,不得已去拿鎖。 版本號 + 重試
mysql 常見的鎖有 頁級鎖,表級鎖咪奖,行級鎖
鎖算法有,record lock 記錄鎖酱床,鎖數(shù)據(jù)用于等號查找數(shù)據(jù)
Gap 鎖羊赵,不鎖記錄只鎖gap
next-key 鎖 同時鎖住記錄(數(shù)據(jù)),并且鎖住記錄前面的Gap
mysql 中死鎖
表級鎖不會產(chǎn)生死鎖.所以解決死鎖主要還是針對于最常用的InnoDB.
死鎖的關(guān)鍵在于:兩個(或以上)的Session加鎖的順序不一致扇谣。
情景1 : 鎖的順序不一致
例如兩個用戶同時投資昧捷,A用戶金額隨機分為2份,分給借款人1罐寨,2
B用戶金額隨機分為2份靡挥,分給借款人2,1
由于加鎖的順序不一樣鸯绿,死鎖當然很快就出現(xiàn)了芹血。
對于這個問題的改進很簡單贮泞,直接把所有分配到的借款人直接一次鎖住就行了。
Select * from xxx where id in (xx,xx,xx) for update
在in里面的列表值mysql是會自動從小到大排序幔烛,加鎖也是一條條從小到大加的鎖
情景2: 鎖在查詢中表中不存在改值
select * from t3 where id=22 for update;
當對存在的行進行鎖的時候(主鍵)啃擦,mysql就只有行鎖。
當對未存在的行進行鎖的時候(即使條件為主鍵)饿悬,mysql是會鎖住一段范圍(有g(shù)ap鎖)
例如 現(xiàn)在表中有 11,12 鎖住 12 到無窮大
表中 11,30 鎖住 11,30
insert into t3(xx,xx) on duplicate key update `xx`='XX';
用mysql特有的語法來解決此問題令蛉。因為insert語句對于主鍵來說,插入的行不管有沒有存在狡恬,都會只有行鎖珠叔。
java中死鎖的檢測
jps 找到進程號 ,jstack -l
jconsole
虛擬內(nèi)存的作用
- 將主存視為一個存儲在磁盤上的地址空間的高速緩存弟劲,在主存中只保存活動區(qū)域祷安,并根據(jù)需要在磁盤和主存之間來回傳送數(shù)據(jù)
- 為每個進程提供了一致的地址空間,簡化內(nèi)存管理
- 保護了每個進程的地址空間不被其他進程破壞
VM系統(tǒng)將虛擬內(nèi)存分割為大小固定的塊兔乞,稱為虛擬頁(VP)汇鞭,來作為磁盤和主存之間的傳輸單元。
頁表用于地址轉(zhuǎn)換同時標注當前頁是否在物理頁中庸追,同時也關(guān)聯(lián)了具體的物理頁的具體物理地址霍骄。
操作系統(tǒng)為每個進程提供一個獨立的頁表
,因而也就是獨立的虛擬地址空間淡溯。
獨立地址空間允許每個進程的內(nèi)存映像使用相同的基本格式读整。
操作系統(tǒng)不允許用戶進程修改只讀代碼段,共享虛擬頁表咱娶,其他進程私有內(nèi)存
請求分頁實現(xiàn)虛擬內(nèi)存
請求分頁系統(tǒng)建立在基本分頁系統(tǒng)基礎之上米间,為了支持虛擬存儲器功能而增加了請求調(diào)頁功能和頁面置換功能。請求分頁是目前最常用的一種實現(xiàn)虛擬存儲器的方法膘侮。
在請求分頁系統(tǒng)中车伞,只要求將當前需要的一部分頁面裝入內(nèi)存,便可以啟動作業(yè)運行喻喳。在作業(yè)執(zhí)行過程中另玖,當所要訪問的頁面不在內(nèi)存時,再通過調(diào)頁功能將其調(diào)入表伦,同時還可以通過置換功能將暫時不用的頁面換出到外存上谦去,以便騰出內(nèi)存空間。
文件系統(tǒng) inode 和 block
inode 索引節(jié)點蹦哼,用來存放文件屬性的空間鳄哭,通過inode 號碼來找到這個空間
1.node 是存放文件屬性
2.我們每創(chuàng)建一個文件占用一個inode(一般256字節(jié))
3.inode 還會存放block的位置信息(指向)
4.inode 節(jié)點號相同的文件,互為硬鏈接文件纲熏,可以理解為是一個文件的 不同入口(一個超市妆丘,多個入口)
硬鏈接數(shù)量—文件入口數(shù)量
5.inode 號碼在一個分區(qū)(文件系統(tǒng))是唯一的锄俄。
軟連接與硬鏈接
A是B的硬鏈接(A和B都是文件名),則A的目錄項中的inode節(jié)點號與B的目錄項中的inode節(jié)點號相同勺拣,即一個inode節(jié)點對應兩個不同的文件名奶赠,兩個文件名指向同一個文件,A和B對文件系統(tǒng)來說是完全平等的药有。如果刪除了其中一個毅戈,對另外一個沒有影響。每增加一個文件名愤惰,inode節(jié)點上的鏈接數(shù)增加一苇经,每刪除一個對應的文件名,inode節(jié)點上的鏈接數(shù)減一宦言,直到為0扇单,inode節(jié)點和對應的數(shù)據(jù)塊被回收。
A是B的軟鏈接(A和B都是文件名)奠旺,A的目錄項中的inode節(jié)點號與B的目錄項中的inode節(jié)點號不相同蜘澜,A和B指向的是兩個不同的inode,繼而指向兩塊不同的數(shù)據(jù)塊凉倚。但是A的數(shù)據(jù)塊中存放的只是B的路徑名(可以根據(jù)這個找到B的目錄項)。A和B之間是“主從”關(guān)系嫂沉,如果B被刪除了稽寒,A仍然存在(因為兩個是不同的文件),但指向的是一個無效的鏈接趟章。
硬鏈接:
a.不能對目錄創(chuàng)建硬鏈接杏糙,原因有幾種,最重要的是:文件系統(tǒng)不能存在鏈接環(huán)(目錄創(chuàng)建時的".."除外蚓土,這個系統(tǒng)可以識別出來),存在環(huán)的后果會導致例如文件遍歷等操作的混亂(du宏侍,pwd等命令的運作原理就是基于文件硬鏈接,順便一提蜀漆,ls -l結(jié)果的第二列也是文件的硬鏈接數(shù)谅河,即inode節(jié)點的鏈接數(shù))
b:不能對不同的文件系統(tǒng)創(chuàng)建硬鏈接,即兩個文件名要在相同的文件系統(tǒng)下。
c:不能對不存在的文件創(chuàng)建硬鏈接确丢,由原理即可知原因绷耍。
軟鏈接:
a.可以對目錄創(chuàng)建軟鏈接,遍歷操作會忽略目錄的軟鏈接鲜侥。
b:可以跨文件系統(tǒng)
c:可以對不存在的文件創(chuàng)建軟鏈接褂始,因為放的只是一個字符串,至于這個字符串是不是對于一個實際的文件描函,就是另外一回事了
僵尸進程和孤兒進程
1崎苗、孤兒進程:子進程執(zhí)行完畢時發(fā)現(xiàn)父進程已退出狐粱,子進程變成為了孤兒進程。孤兒進程后期會被系統(tǒng)的 init 進程接管胆数,并 wait/waitpid 其執(zhí)行狀態(tài)做回收處理肌蜻。對系統(tǒng)并無危害。
2幅慌、僵尸進程:子進程執(zhí)行完畢時發(fā)現(xiàn)父進程未退出宋欺,會向父進程發(fā)送 SIGCHLD 信號。但父進程沒有使用 wait/waitpid 或其他方式處理 SIGCHLD 信號來回收子進程胰伍,子進程變成為了對系統(tǒng)有害的僵尸進程齿诞。
僵尸進程無法被系統(tǒng)有效的回收,ps 查看時狀態(tài)為 Z 的即為僵尸進程骂租,或 top命令可直接看到 zombie 的個數(shù)祷杈。僵尸進程的父進程此時一定仍在運行,產(chǎn)生僵尸進程的元兇其實是他們的父進程渗饮,殺掉父進程但汞,僵尸進程就變?yōu)榱斯聝哼M程,便可以轉(zhuǎn)交給 init 進程回收處理互站。
僵尸進程對系統(tǒng)的影響:
如果進程不調(diào)用wait()或waitpid()的話私蕾,那么保留的信息就不會釋放,其進程號就會一直被占用胡桃,但是系統(tǒng)所能使用的進程號是有限的踩叭,如果大量的產(chǎn)生僵死進程,將因為沒有可用的進程號而導致系統(tǒng)不能產(chǎn)生新的進程. 此即為僵尸進程的危害翠胰,應當避免容贝。
外部解決辦法:
kill掉父進程,使僵尸進程變?yōu)楣聝哼M程之景。
內(nèi)部解決辦法:
1斤富、父進程處理SIGCHLD信號,在信號處理函數(shù)中調(diào)用wait處理僵尸進程锻狗。
2满力、fork兩次:借助一個中間進程,父進程只wait中間進程轻纪,讓中間進程再fork出孫進程脚囊。孫進程結(jié)束后會變成僵尸進程,等中間進程一結(jié)束桐磁,孫進程就成孤兒進程了悔耘。孤兒進程對系統(tǒng)的影響:
孤兒進程并不會有什么危害,init進程會接管并處理掉它我擂。
集線器 衬以,交換機 和 路由器
- 集線器工作在物理層缓艳,信號在線路中傳播會進行衰減,集線器的作用就是對信號進行再生放大看峻,從而擴大了網(wǎng)絡的傳輸距離阶淘。集線器的網(wǎng)絡叫做共享式網(wǎng)絡,該網(wǎng)絡的所有主機都屬于同一個沖突域互妓,即一臺計算機發(fā)送消息溪窒,其它的計算機都能夠收到。而且同一時刻只能夠有一臺計算機發(fā)送消息(為了防止沖突)冯勉。會進行分流澈蚌。
- 交換機工作在數(shù)據(jù)鏈路層,集線器的信道利用率太低了灼狰,所以就出現(xiàn)了交換機宛瞄。交換機很很多個端口,每個端口都能夠連接一臺計算機交胚,當計算機A向計算機B發(fā)送信息時份汗,會在內(nèi)部建立起一條臨時性的數(shù)據(jù)傳輸通道,如果有多臺計算機同時通信蝴簇,那么就會維護多條通道杯活。那么可以看出交換機的每個端口就是一個沖突域,如果該端口只連接了一臺計算機熬词,那么就相當于沒有沖突旁钧。
- 路由器工作在網(wǎng)絡層,那么路由器A怎么知道把IP數(shù)據(jù)包從哪個端口送出去呢荡澎?路由器內(nèi)部維護了一張路由表均践,它知道把IP數(shù)據(jù)報從哪個端口發(fā)出去晤锹。交換機是工作在數(shù)據(jù)鏈路層的摩幔,也即交換機只能轉(zhuǎn)發(fā)局域網(wǎng)內(nèi)的幀。如果網(wǎng)絡A的主機想要發(fā)消息給網(wǎng)絡B的主機就需要路由器了鞭铆。
ip數(shù)據(jù)包常用字段
首部長度或衡,總長度,標識(IP軟件在存儲器中維持一個計數(shù)器车遂,每產(chǎn)生一個數(shù)據(jù)報封断,計數(shù)器 就加1,并將此值賦給標識字段舶担。)標志(標志字段中的最低位記為MF(More Fragment)坡疼。MF=1即表示后面“還有分片”的數(shù)據(jù)報。MF=0表示這已是若干數(shù)據(jù)報片中的最后一個衣陶,標志字段中間的一位記為DF(Don’tFragment)柄瑰,意思是“不能分片”闸氮。只有當DF=0時才允許分片。)片偏移教沾,(片偏移指出:較長的分組在分片后蒲跨,某片在原分組中的相對位置。也就是說授翻,相對用戶數(shù)據(jù)字段的起點或悲,該片從何處開始。)ttl生存時間堪唐,首部校驗和
ARP 緩存建立過程
每臺主機都會在自己的ARP緩沖區(qū)中建立一個 ARP列表巡语,以表示IP地址和MAC地址的對應關(guān)系。當源主機需要將一個數(shù)據(jù)包要發(fā)送到目的主機時羔杨,會首先檢查自己 ARP列表中是否存在該 IP地址對應的MAC地址捌臊,如果有,就直接將數(shù)據(jù)包發(fā)送到這個MAC地址兜材;如果沒有理澎,就向本地網(wǎng)段發(fā)起一個ARP請求的廣播包,查詢此目的主機對應的MAC地址曙寡。此ARP請求數(shù)據(jù)包里包括源主機的IP地址糠爬、硬件地址、以及目的主機的IP地址举庶。網(wǎng)絡中所有的主機收到這個ARP請求后执隧,會檢查數(shù)據(jù)包中的目的IP是否和自己的IP地址一致。如果不相同就忽略此數(shù)據(jù)包户侥;如果相同镀琉,該主機首先將發(fā)送端的MAC地址和IP地址添加到自己的ARP列表中,如果ARP表中已經(jīng)存在該IP的信息蕊唐,則將其覆蓋屋摔,然后給源主機發(fā)送一個 ARP響應數(shù)據(jù)包,告訴對方自己是它需要查找的MAC地址替梨;源主機收到這個ARP響應數(shù)據(jù)包后钓试,將得到的目的主機的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息開始數(shù)據(jù)的傳輸副瀑。如果源主機一直沒有收到ARP響應數(shù)據(jù)包弓熏,表示ARP查詢失敗。
廣播糠睡,單播
ICMP 作用
是 IP協(xié)議的一個重要組成部分挽鞠。
ICMPv6報文總體上被分為兩種類型:差錯報文和信息報文。
控制消息是指網(wǎng)絡通不通、主機是否可達信认、路由是否可用等網(wǎng)絡本身的消息串稀。這些控制消息雖然并不傳輸用戶數(shù)據(jù),但是對于用戶數(shù)據(jù)的傳遞起著重要的作用狮杨。
ICMP不能糾正差錯母截,它只是報告差錯。差錯處理需要由高層協(xié)議去完成橄教。
mysql 連接查詢和分組查詢
MySQL Join
- 笛卡爾積
select * from t1 join t2;
- 左連接
select * from t1 left join t2 on t1.id = t2.id;
- 右連接
select * from t1 right join t2 on t1.id = t2.id;
- 內(nèi)連接
select * from t1 inner join t2 on t1.id = t2.id;
- 左表獨有
select * from t1 left join t2 on t1.id = t2.id where t2.id is null;
- 右表獨有
select * from t1 right join t2 on t1.id = t2.id where t1.id is null;
- 全連接 union
左連接 union 右連接
- 并集去交集
左表獨有 union 右表獨有
- select count(*) as studentNum, groupId,sex from student group by groupId,sex;
表連接查詢和子查詢的區(qū)別
表關(guān)聯(lián)是可以利用兩個表的索引的清寇,如果是用子查詢,至少第二次查詢是沒有辦法使用索引的护蝶。
將子查詢轉(zhuǎn)換為連接查詢华烟。
原因:子查詢會多次運算查詢,連接查詢利于優(yōu)化器優(yōu)化持灰,而且可以使用多線程查詢各個連接子句盔夜。
drop, truncate, delete 比較
- truncate 和 delete 只刪除數(shù)據(jù)不刪除表的結(jié)構(gòu)(定義)
- delete 語句是數(shù)據(jù)庫操作語言(dml),這個操作會放到 rollback segement 中堤魁,事務提交之后才生效喂链;如果有相應的 trigger,執(zhí)行的時候?qū)⒈挥|發(fā)妥泉。
- 速度椭微,一般來說: drop> truncate > delete
- truncate、drop 是數(shù)據(jù)庫定義語言(ddl)盲链,操作立即生效蝇率,原數(shù)據(jù)不放到 rollback segment 中,不能回滾刽沾,操作不觸發(fā)trigger本慕。
mysql 視圖
視圖就是一條SELECT語句執(zhí)行后返回的結(jié)果集,
視圖是一個虛擬表,同真實的表一樣侧漓,視圖包含一系列帶有名稱的列和行數(shù)據(jù)锅尘。但是,視圖并不在數(shù)據(jù)庫中以存儲的數(shù)據(jù)值集形式存在火架。行和列數(shù)據(jù)來自由定義視圖的查詢所引用的表鉴象。
視圖的作用:
(1)簡化用戶的操作
關(guān)鍵信息來源于多個復雜關(guān)聯(lián)表忙菠,可以創(chuàng)建視圖提取我們需要的信息何鸡,
簡化操作;
(2)對機密數(shù)據(jù)提供保護作用
不希望用戶訪問表中某些含敏感信息的列牛欢,比如salary
視圖是否可以更新
(1)若視圖的字段是來自字段表達式或常數(shù)骡男,則不允許對此視圖執(zhí)行INSERT、UPDATE操作傍睹,允許執(zhí)行DELETE操作隔盛;
(2)若視圖的字段是來自庫函數(shù)犹菱,則此視圖不允許更新;
(3)若視圖的定義中有GROUP BY子句或聚集函數(shù)時吮炕,則此視圖不允許更新腊脱;
(4)若視圖的定義中有DISTINCT任選項,則此視圖不允許更新龙亲;
(5)若視圖的定義中有嵌套查詢陕凹,并且嵌套查詢的FROM子句中涉及的表也是導出該視圖的基表,則此視圖不允許更新鳄炉;
(6)若視圖是由兩個以上的基表導出的杜耙,此視圖不允許更新;
(7)一個不允許更新的視圖上定義的視圖也不允許更新拂盯;
(8)由一個基表定義的視圖佑女,只含有基表的主鍵或候補鍵,并且視圖中沒有用表達式或函數(shù)定義的屬性谈竿,才允許更新团驱。
哪類視圖是可以更新的?哪類視圖是不可更新的空凸?各舉一例說明店茶。
答:基本表的行列子集視圖一般是可更新的。若視圖的屬性來自集函數(shù)劫恒、表達式贩幻,則該視圖肯定是不可以更新的。
存儲過程和觸發(fā)器
存儲過程與觸發(fā)器因為在數(shù)據(jù)庫中的作用不同两嘴,因為也就沒什么性能可比性丛楚。
存儲過程(StoredProcedure)是一組為了完成特定功能的SQL語句集,經(jīng)編譯后存儲在數(shù)據(jù)庫中憔辫。用戶通過指定存儲過程的名字并給出參數(shù)(如果該存儲過程帶有參數(shù))來執(zhí)行它趣些。存儲過程是數(shù)據(jù)庫中的一個重要對象,任何一個設計良好的數(shù)據(jù)庫應用程序都應該用到存儲過程贰您。觸發(fā)器(trigger)是個特殊的存儲過程坏平,它的執(zhí)行不是由程序調(diào)用,也不是手工啟動锦亦,而是由事件來觸發(fā)舶替,比如當對一個表進行操作(insert,delete杠园,update)時就會激活它執(zhí)行顾瞪。觸發(fā)器經(jīng)常用于加強數(shù)據(jù)的完整性約束和業(yè)務規(guī)則等。 觸發(fā)器可以從 DBA_TRIGGERS,USER_TRIGGERS 數(shù)據(jù)字典中查到陈醒。
事務 ACID
原子性:事務中的所有操作作為一個整體像原子一樣不可分割惕橙,要么全部成功,要么全部失敗钉跷。
原子性的實現(xiàn)原理弥鹦,回滾日志(undo log),當事務回滾時能撤銷所有已經(jīng)成功的SQL語句。
如果事務執(zhí)行失敗或調(diào)用了rollback,便可以利用undo log 中信息回滾到之前狀態(tài)爷辙。
一致性:事務開始前和結(jié)束后惶凝,數(shù)據(jù)庫的完整性約束沒有被破壞,都是合法的數(shù)據(jù)狀態(tài)犬钢。
一致性:保證原子性苍鲜,持久性,隔離性
隔離性:并發(fā)執(zhí)行的事務不會相互影響玷犹,其對數(shù)據(jù)庫的影響和它們串行執(zhí)行時一樣混滔。
嚴格的隔離性,對應了事務,采用鎖機制和MVCC
持久性:事務一旦提交歹颓,其對數(shù)據(jù)庫的更新就是持久的坯屿。任何事務或系統(tǒng)故障都不會導致數(shù)據(jù)丟失。
innodb 作為mysql 的存儲引擎巍扛,數(shù)據(jù)是存放在磁盤中的领跛,同時innodb提供了buffer pool,作為數(shù)據(jù)庫的緩沖。 當從數(shù)據(jù)庫進行讀數(shù)據(jù)時撤奸,會先從buffer pool 中讀取吠昭,如果沒有從磁盤讀入放入buffer pool,
當向數(shù)據(jù)庫寫數(shù)據(jù)時,先寫buffer pool,buffer pool 會定期刷到磁盤(刷臟)
問題是如果mysql 宕機胧瓜,而此時buffer pool 中數(shù)據(jù)矢棚,沒有刷到磁盤就會丟失。
redo log 記錄寫到 buffer pool中的操作府喳。
如何避免數(shù)據(jù)庫一致性被破壞
并發(fā)控制技術(shù):保證了事務的隔離性蒲肋,使數(shù)據(jù)庫的一致性不會因為并發(fā)執(zhí)行被操作
日志恢復技術(shù):保證了事務的原子性,使數(shù)據(jù)庫的一致性不會因事務或系統(tǒng)故障被破壞钝满。同時使已提交的對數(shù)據(jù)庫的修改不會因系統(tǒng)崩潰而丟失兜粘,保證了事務的持久性。
next-key 鎖解決幻讀(當前讀)
innodb 的鎖算法有三種: record lock, gap lock, next-key lock,
next-key lock 就是 record + gap 的綜合
鎖的類型可以劃分為共享鎖和排他鎖
next-key 可以解決(當前讀 select * for update) 的幻讀問題弯蚜。
innodb中的RR隔離級別是通過next-key locking是如何解決幻讀問題的孔轴,就是鎖住一個范圍。
路由器是如何感知擁塞的熟吏?
- 路由器如何感知發(fā)生了擁塞:通過路由器輸出端口的排隊時延
- 路由器間的鏈路會按照時延來設置權(quán)值大小距糖,時延小的權(quán)值小,在進行網(wǎng)絡傳輸時會將鏈路進行排隊
跳表的實現(xiàn)
跳表的實現(xiàn)是基于雙向鏈表牵寺,每一個節(jié)點都有一定的概率向上生成一層節(jié)點悍引,所以快表的節(jié)點是
跳表節(jié)點詳情:(key, value, up, down, left, right)
每一層都是創(chuàng)建一個head, tail 做鏈表,查詢的時候順序遍歷到尾結(jié)束或者大于結(jié)束帽氓,否則下一層
put過程:創(chuàng)建的時候趣斤,找到節(jié)點,key一致替換value, 否則二分之一的概率隨機上一層黎休,創(chuàng)建頭尾浓领,關(guān)聯(lián)左右聯(lián)系,上下聯(lián)系势腮,同時找前一個有上層節(jié)點的值联贩,上一層將當前節(jié)點鏈接坑赡,迭代掸宛,直到隨機失敗
zookeeper 的應用場景有?
zookeeper的應用場景是命名服務管理馒过,集群管理(master選舉)署照,分布式鎖祸泪,配置管理,負載均衡
mysql 分庫分表如何將一個表進行拆分建芙?
方案1: 分庫分表自增id解決方案没隘,1. 創(chuàng)建一個表 id,stab, 所有進程去插入,會生成一個id,然后查詢拿到這個自增id禁荸,用這個id作為不同表的id, 缺點是性能不好右蒲。
方案2:采用方案1的方法,也是創(chuàng)建一個表赶熟,只是這次一次分配一個id段品嚣,可以將表創(chuàng)建為id,start, step,... 直接為每一個表分配一個段,這個表使用完钧大,才會在來進行申請翰撑。
方案3:采用雪花算法,41bit時間戳+10位機器id,12位序列號
ES 分片的個數(shù)設置
一般一個分片大小在30~50GB啊央,可以根據(jù)數(shù)據(jù)量設置分片的個數(shù)
可以設置為節(jié)點個數(shù)的1.5~3倍
增強for 和普通的for的區(qū)別眶诈?
增強for的底層就是迭代器,所以使用增加for遍歷LinkedList比較快
使用普通for遍歷ArrayList比較快
Arrays.asList() 將數(shù)組轉(zhuǎn)化list如何實現(xiàn)的瓜饥?
Arrays.asList() 底層任然是數(shù)組逝撬,只是增加了適配器。
hashmap 1.8 的hash怎么做的乓土?
hashmap 1.8 沒有進行重hash, 采用原位置 + oldtable長度
socket中的編程事件有什么宪潮?
socket編程中的事件: OP_CONNECT, OP_ACCEPT
threadLocalMap 和 HashMap 的區(qū)別溯警?
threadLocal 在每個線程內(nèi)維護一個threadLocalMap, key 是threadLocal的弱引用,value是放入的值狡相,threadLocalMap 中并沒有鏈表梯轻,所以尋址方法是,線性開放定址法尽棕。ThreadLocal的hash算法喳挑,每新創(chuàng)建一個增加斐波那契數(shù),均勻分布hash
ThreadLocal.get()的時候,發(fā)生GC之后滔悉,key是否是null伊诵?
弱引用,只要發(fā)生gc就會回收
但是回官, get 的時候?qū)儆趶娨貌苎纾粫厥?/p>
TreeSet 是如何比較對象相等的?
TreeSet 底層是TreeMap TreeMap 比較對象相等使用的是 compareTo歉提, 底層是歸并排序
Integer, Long,String 的hashCode 算法
hashcode 的大小都是int, Integer 的hashcode 是其本身,Long hashcode 本身右移32 異或變?yōu)閕nt浙炼,String hashCode 將其以char數(shù)字的形式轉(zhuǎn)31進制
不使用Synchronized 創(chuàng)建單利設計模式?
https://zhuanlan.zhihu.com/p/140479178
redis 的批處理命令唯袄?
redis 批量處理的指令有弯屈, pipeling/transcation/mget,mset
http://www.reibang.com/p/75137d23ae4a
redis 采用的是典型的tcp交換,在一次round trip 中恋拷,發(fā)送一條命令资厉,其中的開銷 socket IO 上下文切換,執(zhí)行蔬顾,競爭宴偿,mget 只能處理string hash等
管道pipeling,意味著客戶端可以在一次請求中發(fā)送多個命令,沒有任何事務保證诀豁,其他命令可能在其中執(zhí)行
事務窄刘, 具備原子性,multi, exec事務的所有命令會分批發(fā)送給redis實例舷胜,redis返回+QUEUED娩践,表示命令已入列,但是不會執(zhí)行任何命令烹骨。在收到EXEC命令時翻伺,一次執(zhí)行本事務的所有命令。因此事務的性能略低于pipeline沮焕,但是相差不多吨岭。
說一下AOF重寫的實現(xiàn)細節(jié)?
為了解決AOF文件體積膨脹的問題峦树,Redis提供了AOF重寫功能:Redis服務器可以創(chuàng)建一個新的AOF文件來替代現(xiàn)有的AOF文件
當前列表鍵list在數(shù)據(jù)庫中的值就為["C", "D", "E", "F", "G"]辣辫。要使用盡量少的命令來記錄list鍵的狀態(tài)旦事,最簡單的方式不是去讀取和分析現(xiàn)有AOF文件的內(nèi)容,急灭,而是直接讀取list鍵在數(shù)據(jù)庫中的當前值姐浮,然后用一條RPUSH list "C" "D" "E" "F" "G"代替前面的6條命令。
相當于命令壓縮
這個函數(shù)會進行大量的寫入操作化戳,所以調(diào)用這個函數(shù)的線程將被長時間的阻塞
Redis不希望AOF重寫會造成服務器無法處理請求单料,所以Redis決定將AOF重寫程序放到子進程(后臺)里執(zhí)行埋凯。子進程進行AOF重寫期間点楼,主進程可以繼續(xù)處理命令請求;
子進程帶有主進程的數(shù)據(jù)副本白对,使用子進程而不是線程掠廓,可以避免在鎖的情況下,保證數(shù)據(jù)的安全性甩恼。
Redis增加了一個AOF重寫緩存蟀瞧,這個緩存在fork出子進程之后開始啟用,Redis服務器主進程在執(zhí)行完寫命令之后条摸,會同時將這個寫命令追加到AOF緩沖區(qū)和AOF重寫緩沖區(qū)
ArrayList 存放的最大值悦污?
ArrayList 可以裝下的最大數(shù) Integer 最大值 減8
Arrays.Sort() 實現(xiàn)原理?
Arrays.sort() 底層 大于 286 使用 快排钉蒲, 大于 47 使用優(yōu)化的帶前哨的pair插入排序切端,小于47 使用不帶前哨的插入排序
那你詳細說下最小生成樹算法?
kruskal 算法顷啼,稱為加邊法踏枣,將邊的權(quán)值進行排序,每次從中選擇最小的滿足條件的加入钙蒙,加入的不能形成回路茵瀑,直到所有的點都已經(jīng)加入
prim 算法,加點法躬厌,每次加入代價最小的邊所對應的點马昨,并將點加入集合,以當前點集合篩選下一個最小的權(quán)值邊扛施,加入集合
為什么對象年齡達到15進入老年代偏陪?
為什么15進入老年代,主要原因是對象的分代年齡占4位煮嫌,最大值也就15
那你詳細說下空間分配擔保策略笛谦?
空間分配擔保策略,新生代使用復制算法昌阿,如果出現(xiàn)大量的對象在Minor gc 后任然存活饥脑,就需要老年代進行分配擔保恳邀,把Survivor無法容納的對象直接進入老年代。老年代需要擔保灶轰,老年代剩余的空間谣沸,可以容納新生代區(qū)域
redis setnx 使用注意什么?
redis 鎖 setnx 設置時加上 過期時間笋颤,可以防止一個線程拿到鎖還沒執(zhí)行掛了乳附,一直不釋放的情況
其次還可能出現(xiàn)的情況時過期時間到了還沒執(zhí)行完,另一個線程搶占到了伴澄,這時候第一個線程執(zhí)行完了赋除,并執(zhí)行del, 把b的鎖刪除了,可以在刪除前進行判斷一下防止誤刪非凌,可以使用lua腳本實習判斷举农,怎么實現(xiàn)續(xù)航,可以讓A開一個守護線程敞嗡,當時間快到期延時一下