ThreadLocal(線程變量副本)
Synchronized實(shí)現(xiàn)內(nèi)存共享,ThreadLocal為每個(gè)線程維護(hù)一個(gè)本地變量。
采用空間換時(shí)間,它用于線程間的數(shù)據(jù)隔離,為每一個(gè)使用該變量的線程提供一個(gè)副本,每個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)和其他線程的副本沖突。
ThreadLocal類中維護(hù)一個(gè)Map,用于存儲(chǔ)每一個(gè)線程的變量副本,Map中元素的鍵為線程對(duì)象,而值為對(duì)應(yīng)線程的變量副本。
ThreadLocal在Spring中發(fā)揮著巨大的作用,在管理Request作用域中的Bean、事務(wù)管理、任務(wù)調(diào)度、AOP等模塊都出現(xiàn)了它的身影。
Spring中絕大部分Bean都可以聲明成Singleton作用域,采用ThreadLocal進(jìn)行封裝,因此有狀態(tài)的Bean就能夠以singleton的方式在多線程中正常工作了。
Java虛擬機(jī)規(guī)范中將Java運(yùn)行時(shí)數(shù)據(jù)分為六種。
1.程序計(jì)數(shù)器:是一個(gè)數(shù)據(jù)結(jié)構(gòu),用于保存當(dāng)前正常執(zhí)行的程序的內(nèi)存地址。Java虛擬機(jī)的多線程就是通過(guò)線程輪流切換并分配處理器時(shí)間來(lái)實(shí)現(xiàn)的,為了線程切換后能恢復(fù)到正確的位置,每條線程都需要一個(gè)獨(dú)立的程序計(jì)數(shù)器,互不影響,該區(qū)域?yàn)椤熬€程私有”。
2.Java虛擬機(jī)棧:線程私有的,與線程生命周期相同,用于存儲(chǔ)局部變量表,操作棧,方法返回值。局部變量表放著基本數(shù)據(jù)類型,還有對(duì)象的引用。
3.本地方法棧:跟虛擬機(jī)棧很像,不過(guò)它是為虛擬機(jī)使用到的Native方法服務(wù)。
4.Java堆:所有線程共享的一塊內(nèi)存區(qū)域,對(duì)象實(shí)例幾乎都在這分配內(nèi)存。
5.方法區(qū):各個(gè)線程共享的區(qū)域,儲(chǔ)存虛擬機(jī)加載的類信息,常量,靜態(tài)變量,編譯后的代碼。
6.運(yùn)行時(shí)常量池:代表運(yùn)行時(shí)每個(gè)class文件中的常量表。包括幾種常量:編譯時(shí)的數(shù)字常量、方法或者域的引用。
“你能不能談?wù)?,java GC是在什么時(shí)候,對(duì)什么東西,做了什么事情?”
在什么時(shí)候:
1.新生代有一個(gè)Eden區(qū)和兩個(gè)survivor區(qū),首先將對(duì)象放入Eden區(qū),如果空間不足就向其中的一個(gè)survivor區(qū)上放,如果仍然放不下就會(huì)引發(fā)一次發(fā)生在新生代的minor GC,將存活的對(duì)象放入另一個(gè)survivor區(qū)中,然后清空Eden和之前的那個(gè)survivor區(qū)的內(nèi)存。在某次GC過(guò)程中,如果發(fā)現(xiàn)仍然又放不下的對(duì)象,就將這些對(duì)象放入老年代內(nèi)存里去。
2.大對(duì)象以及長(zhǎng)期存活的對(duì)象直接進(jìn)入老年區(qū)。
3.當(dāng)每次執(zhí)行minor GC的時(shí)候應(yīng)該對(duì)要晉升到老年代的對(duì)象進(jìn)行分析,如果這些馬上要到老年區(qū)的老年對(duì)象的大小超過(guò)了老年區(qū)的剩余大小,那么執(zhí)行一次Full GC以盡可能地獲得老年區(qū)的空間。
對(duì)什么東西:從GC Roots搜索不到,而且經(jīng)過(guò)一次標(biāo)記清理之后仍沒(méi)有復(fù)活的對(duì)象。
做什么: 新生代:復(fù)制清理; 老年代:標(biāo)記-清除和標(biāo)記-壓縮算法; 永久代:存放Java中的類和加載類的類加載器本身。
GC Roots都有哪些: 1. 虛擬機(jī)棧中的引用的對(duì)象 2. 方法區(qū)中靜態(tài)屬性引用的對(duì)象,常量引用的對(duì)象 3. 本地方法棧中JNI(即一般說(shuō)的Native方法)引用的對(duì)象。
Synchronized 與Lock都是可重入鎖,同一個(gè)線程再次進(jìn)入同步代碼的時(shí)候.可以使用自己已經(jīng)獲取到的鎖。
Synchronized是悲觀鎖機(jī)制,獨(dú)占鎖。而Locks.ReentrantLock是,每次不加鎖而是假設(shè)沒(méi)有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。 ReentrantLock適用場(chǎng)景
某個(gè)線程在等待一個(gè)鎖的控制權(quán)的這段時(shí)間需要中斷
需要分開處理一些wait-notify,ReentrantLock里面的Condition應(yīng)用,能夠控制notify哪個(gè)線程,鎖可以綁定多個(gè)條件。
具有公平鎖功能,每個(gè)到來(lái)的線程都將排隊(duì)等候。
StringBuffer是線程安全的,每次操作字符串,String會(huì)生成一個(gè)新的對(duì)象,而StringBuffer不會(huì);StringBuilder是非線程安全的
fail-fast:機(jī)制是java集合(Collection)中的一種錯(cuò)誤機(jī)制。當(dāng)多個(gè)線程對(duì)同一個(gè)集合的內(nèi)容進(jìn)行操作時(shí),就可能會(huì)產(chǎn)生fail-fast事件。
例如:當(dāng)某一個(gè)線程A通過(guò)iterator去遍歷某集合的過(guò)程中,若該集合的內(nèi)容被其他線程所改變了;那么線程A訪問(wèn)集合時(shí),就會(huì)拋出ConcurrentModificationException異常,產(chǎn)生fail-fast事件
happens-before:如果兩個(gè)操作之間具有happens-before 關(guān)系,那么前一個(gè)操作的結(jié)果就會(huì)對(duì)后面一個(gè)操作可見。
1.程序順序規(guī)則:一個(gè)線程中的每個(gè)操作,happens- before 于該線程中的任意后續(xù)操作。
2.監(jiān)視器鎖規(guī)則:對(duì)一個(gè)監(jiān)視器鎖的解鎖,happens- before 于隨后對(duì)這個(gè)監(jiān)視器鎖的加鎖。
3.volatile變量規(guī)則:對(duì)一個(gè)volatile域的寫,happens- before于任意后續(xù)對(duì)這個(gè)volatile域的讀。
4.傳遞性:如果A happens- before B,且B happens- before C,那么A happens- before C。
5.線程啟動(dòng)規(guī)則:Thread對(duì)象的start()方法happens- before于此線程的每一個(gè)動(dòng)作。
Volatile和Synchronized四個(gè)不同點(diǎn):
1 粒度不同,前者針對(duì)變量 ,后者鎖對(duì)象和類
2 syn阻塞,volatile線程不阻塞
3 syn保證三大特性,volatile不保證原子性
4 syn編譯器優(yōu)化,volatile不優(yōu)化 volatile具備兩種特性:
1.保證此變量對(duì)所有線程的可見性,指一條線程修改了這個(gè)變量的值,新值對(duì)于其他線程來(lái)說(shuō)是可見的,但并不是多線程安全的。
2.禁止指令重排序優(yōu)化。
Volatile如何保證內(nèi)存可見性:
1.當(dāng)寫一個(gè)volatile變量時(shí),JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存中的共享變量刷新到主內(nèi)存。
2.當(dāng)讀一個(gè)volatile變量時(shí),JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存置為無(wú)效。線程接下來(lái)將從主內(nèi)存中讀取共享變量。
同步:就是一個(gè)任務(wù)的完成需要依賴另外一個(gè)任務(wù),只有等待被依賴的任務(wù)完成后,依賴任務(wù)才能完成。
異步:不需要等待被依賴的任務(wù)完成,只是通知被依賴的任務(wù)要完成什么工作,只要自己任務(wù)完成了就算完成了,被依賴的任務(wù)是否完成會(huì)通知回來(lái)。(異步的特點(diǎn)就是通知)。 打電話和發(fā)短信來(lái)比喻同步和異步操作。
阻塞:CPU停下來(lái)等一個(gè)慢的操作完成以后,才會(huì)接著完成其他的工作。
非阻塞:非阻塞就是在這個(gè)慢的執(zhí)行時(shí),CPU去做其他工作,等這個(gè)慢的完成后,CPU才會(huì)接著完成后續(xù)的操作。
非阻塞會(huì)造成線程切換增加,增加CPU的使用時(shí)間能不能補(bǔ)償系統(tǒng)的切換成本需要考慮。
CAS(Compare And Swap) 無(wú)鎖算法: CAS是樂(lè)觀鎖技術(shù),當(dāng)多個(gè)線程嘗試使用CAS同時(shí)更新同一個(gè)變量時(shí),只有其中一個(gè)線程能更新變量的值,而其它線程都失敗,失敗的線程并不會(huì)被掛起,而是被告知這次競(jìng)爭(zhēng)中失敗,并可以再次嘗試。CAS有3個(gè)操作數(shù),內(nèi)存值V,舊的預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則什么都不做。
線程池的作用: 在程序啟動(dòng)的時(shí)候就創(chuàng)建若干線程來(lái)響應(yīng)處理,它們被稱為線程池,里面的線程叫工作線程
第一:降低資源消耗。通過(guò)重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗。
第二:提高響應(yīng)速度。當(dāng)任務(wù)到達(dá)時(shí),任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行。
第三:提高線程的可管理性。
常用線程池:ExecutorService 是主要的實(shí)現(xiàn)類,其中常用的有 Executors.newSingleThreadPool(),newFixedThreadPool(),newcachedTheadPool(),newScheduledThreadPool()。
類加載器工作機(jī)制:
1.裝載:將Java二進(jìn)制代碼導(dǎo)入jvm中,生成Class文件。
2.連接:a)校驗(yàn):檢查載入Class文件數(shù)據(jù)的正確性 b)準(zhǔn)備:給類的靜態(tài)變量分配存儲(chǔ)空間 c)解析:將符號(hào)引用轉(zhuǎn)成直接引用
3:初始化:對(duì)類的靜態(tài)變量,靜態(tài)方法和靜態(tài)代碼塊執(zhí)行初始化工作。
雙親委派模型:類加載器收到類加載請(qǐng)求,首先將請(qǐng)求委派給父類加載器完成 用戶自定義加載器->應(yīng)用程序加載器->擴(kuò)展類加載器->啟動(dòng)類加載器。
一致性哈希:
Memcahed緩存:
數(shù)據(jù)結(jié)構(gòu):key,value對(duì)
使用方法:get,put等方法
Redis數(shù)據(jù)結(jié)構(gòu): String—字符串(key-value 類型)
Hash—字典(hashmap) Redis的哈希結(jié)構(gòu)可以使你像在數(shù)據(jù)庫(kù)中更新一個(gè)屬性一樣只修改某一項(xiàng)屬性值
List—列表 實(shí)現(xiàn)消息隊(duì)列
Set—集合 利用唯一性
Sorted Set—有序集合 可以進(jìn)行排序 可以實(shí)現(xiàn)數(shù)據(jù)持久化
java自動(dòng)裝箱拆箱深入剖析
談?wù)凧ava反射機(jī)制
如何寫一個(gè)不可變類?
索引:B+,B-,全文索引
Mysql的索引是一個(gè)數(shù)據(jù)結(jié)構(gòu),旨在使數(shù)據(jù)庫(kù)高效的查找數(shù)據(jù)。
常用的數(shù)據(jù)結(jié)構(gòu)是B+Tree,每個(gè)葉子節(jié)點(diǎn)不但存放了索引鍵的相關(guān)信息還增加了指向相鄰葉子節(jié)點(diǎn)的指針,這樣就形成了帶有順序訪問(wèn)指針的B+Tree,做這個(gè)優(yōu)化的目的是提高不同區(qū)間訪問(wèn)的性能。
什么時(shí)候使用索引:
經(jīng)常出現(xiàn)在group by,order by和distinc關(guān)鍵字后面的字段
經(jīng)常與其他表進(jìn)行連接的表,在連接字段上應(yīng)該建立索引
經(jīng)常出現(xiàn)在Where子句中的字段
經(jīng)常出現(xiàn)用作查詢選擇的字段
Spring IOC (控制反轉(zhuǎn),依賴注入)
Spring支持三種依賴注入方式,分別是屬性(Setter方法)注入,構(gòu)造注入和接口注入。
在Spring中,那些組成應(yīng)用的主體及由Spring IOC容器所管理的對(duì)象被稱之為Bean。
Spring的IOC容器通過(guò)反射的機(jī)制實(shí)例化Bean并建立Bean之間的依賴關(guān)系。
簡(jiǎn)單地講,Bean就是由Spring IOC容器初始化、裝配及被管理的對(duì)象。
獲取Bean對(duì)象的過(guò)程,首先通過(guò)Resource加載配置文件并啟動(dòng)IOC容器,然后通過(guò)getBean方法獲取bean對(duì)象,就可以調(diào)用他的方法。
Spring Bean的作用域:
Singleton:Spring IOC容器中只有一個(gè)共享的Bean實(shí)例,一般都是Singleton作用域。
Prototype:每一個(gè)請(qǐng)求,會(huì)產(chǎn)生一個(gè)新的Bean實(shí)例。
Request:每一次http請(qǐng)求會(huì)產(chǎn)生一個(gè)新的Bean實(shí)例。
代理的共有優(yōu)點(diǎn):業(yè)務(wù)類只需要關(guān)注業(yè)務(wù)邏輯本身,保證了業(yè)務(wù)類的重用性。
Java靜態(tài)代理:
代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)了相同的接口,目標(biāo)對(duì)象作為代理對(duì)象的一個(gè)屬性,具體接口實(shí)現(xiàn)中,代理對(duì)象可以在調(diào)用目標(biāo)對(duì)象相應(yīng)方法前后加上其他業(yè)務(wù)處理邏輯。
缺點(diǎn):一個(gè)代理類只能代理一個(gè)業(yè)務(wù)類。如果業(yè)務(wù)類增加方法時(shí),相應(yīng)的代理類也要增加方法。
Java動(dòng)態(tài)代理:
Java動(dòng)態(tài)代理是寫一個(gè)類實(shí)現(xiàn)InvocationHandler接口,重寫Invoke方法,在Invoke方法可以進(jìn)行增強(qiáng)處理的邏輯的編寫,這個(gè)公共代理類在運(yùn)行的時(shí)候才能明確自己要代理的對(duì)象,同時(shí)可以實(shí)現(xiàn)該被代理類的方法的實(shí)現(xiàn),然后在實(shí)現(xiàn)類方法的時(shí)候可以進(jìn)行增強(qiáng)處理。
實(shí)際上:代理對(duì)象的方法 = 增強(qiáng)處理 + 被代理對(duì)象的方法
JDK和CGLIB生成動(dòng)態(tài)代理類的區(qū)別:
JDK動(dòng)態(tài)代理只能針對(duì)實(shí)現(xiàn)了接口的類生成代理(實(shí)例化一個(gè)類)。此時(shí)代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)了相同的接口,目標(biāo)對(duì)象作為代理對(duì)象的一個(gè)屬性,具體接口實(shí)現(xiàn)中,可以在調(diào)用目標(biāo)對(duì)象相應(yīng)方法前后加上其他業(yè)務(wù)處理邏輯
CGLIB是針對(duì)類實(shí)現(xiàn)代理,主要是對(duì)指定的類生成一個(gè)子類(沒(méi)有實(shí)例化一個(gè)類),覆蓋其中的方法 。
Spring AOP應(yīng)用場(chǎng)景
性能檢測(cè),訪問(wèn)控制,日志管理,事務(wù)等。
默認(rèn)的策略是如果目標(biāo)類實(shí)現(xiàn)接口,則使用JDK動(dòng)態(tài)代理技術(shù),如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)接口,則默認(rèn)會(huì)采用CGLIB代理
SpringMVC運(yùn)行原理
客戶端請(qǐng)求提交到DispatcherServlet
由DispatcherServlet控制器查詢HandlerMapping,找到并分發(fā)到指定的Controller中。
Controller調(diào)用業(yè)務(wù)邏輯處理后,返回ModelAndView
DispatcherServlet查詢一個(gè)或多個(gè)ViewResoler視圖解析器,找到ModelAndView指定的視圖
視圖負(fù)責(zé)將結(jié)果顯示到客戶端
一個(gè)Http請(qǐng)求
DNS域名解析 –> 發(fā)起TCP的三次握手 –> 建立TCP連接后發(fā)起http請(qǐng)求 –> 服務(wù)器響應(yīng)http請(qǐng)求,瀏覽器得到html代碼 –> 瀏覽器解析html代碼,并請(qǐng)求html代碼中的資源(如javascript、css、圖片等) –> 瀏覽器對(duì)頁(yè)面進(jìn)行渲染呈現(xiàn)給用戶
設(shè)計(jì)存儲(chǔ)海量數(shù)據(jù)的存儲(chǔ)系統(tǒng):設(shè)計(jì)一個(gè)叫“中間層”的一個(gè)邏輯層,在這個(gè)層,將數(shù)據(jù)庫(kù)的海量數(shù)據(jù)抓出來(lái),做成緩存,運(yùn)行在服務(wù)器的內(nèi)存中,同理,當(dāng)有新的數(shù)據(jù)到來(lái),也先做成緩存,再想辦法,持久化到數(shù)據(jù)庫(kù)中,這是一個(gè)簡(jiǎn)單的思路。主要的步驟是負(fù)載均衡,將不同用戶的請(qǐng)求分發(fā)到不同的處理節(jié)點(diǎn)上,然后先存入緩存,定時(shí)向主數(shù)據(jù)庫(kù)更新數(shù)據(jù)。讀寫的過(guò)程采用類似樂(lè)觀鎖的機(jī)制,可以一直讀(在寫數(shù)據(jù)的時(shí)候也可以),但是每次讀的時(shí)候會(huì)有個(gè)版本的標(biāo)記,如果本次讀的版本低于緩存的版本,會(huì)重新讀數(shù)據(jù),這樣的情況并不多,可以忍受。
Session與Cookie:Cookie可以讓服務(wù)端跟蹤每個(gè)客戶端的訪問(wèn),但是每次客戶端的訪問(wèn)都必須傳回這些Cookie,如果Cookie很多,則無(wú)形的增加了客戶端與服務(wù)端的數(shù)據(jù)傳輸量,
而Session則很好地解決了這個(gè)問(wèn)題,同一個(gè)客戶端每次和服務(wù)端交互時(shí),將數(shù)據(jù)存儲(chǔ)通過(guò)Session到服務(wù)端,不需要每次都傳回所有的Cookie值,而是傳回一個(gè)ID,每個(gè)客戶端第一次訪問(wèn)服務(wù)器生成的唯一的ID,客戶端只要傳回這個(gè)ID就行了,這個(gè)ID通常為NAME為JSESSIONID的一個(gè)Cookie。這樣服務(wù)端就可以通過(guò)這個(gè)ID,來(lái)將存儲(chǔ)到服務(wù)端的KV值取出了。
Session和Cookie的超時(shí)問(wèn)題,Cookie的安全問(wèn)題
分布式Session框架
配置服務(wù)器,Zookeeper集群管理服務(wù)器可以統(tǒng)一管理所有服務(wù)器的配置文件
共享這些Session存儲(chǔ)在一個(gè)分布式緩存中,可以隨時(shí)寫入和讀取,而且性能要很好,如Memcache,Tair。
封裝一個(gè)類繼承自HttpSession,將Session存入到這個(gè)類中然后再存入分布式緩存中
由于Cookie不能跨域訪問(wèn),要實(shí)現(xiàn)Session同步,要同步SessionID寫到不同域名下。
適配器模式:將一個(gè)接口適配到另一個(gè)接口,Java I/O中InputStreamReader將Reader類適配到InputStream,從而實(shí)現(xiàn)了字節(jié)流到字符流的準(zhǔn)換。
裝飾者模式:保持原來(lái)的接口,增強(qiáng)原來(lái)有的功能。
FileInputStream 實(shí)現(xiàn)了InputStream的所有接口,BufferedInputStreams繼承自FileInputStream是具體的裝飾器實(shí)現(xiàn)者,將InputStream讀取的內(nèi)容保存在內(nèi)存中,而提高讀取的性能。
Spring事務(wù)配置方法:
1.切點(diǎn)信息,用于定位實(shí)施事物切面的業(yè)務(wù)類方法
2.控制事務(wù)行為的事務(wù)屬性,這些屬性包括事物隔離級(jí)別,事務(wù)傳播行為,超時(shí)時(shí)間,回滾規(guī)則。
Spring通過(guò)aop/tx Schema 命名空間和@Transaction注解技術(shù)來(lái)進(jìn)行聲明式事物配置。
Mybatis
每一個(gè)Mybatis的應(yīng)用程序都以一個(gè)SqlSessionFactory對(duì)象的實(shí)例為核心。首先用字節(jié)流通過(guò)Resource將配置文件讀入,然后通過(guò)SqlSessionFactoryBuilder().build方法創(chuàng)建SqlSessionFactory,然后再通過(guò)SqlSessionFactory.openSession()方法創(chuàng)建一個(gè)SqlSession為每一個(gè)數(shù)據(jù)庫(kù)事務(wù)服務(wù)。
經(jīng)歷了Mybatis初始化 –>創(chuàng)建SqlSession –>運(yùn)行SQL語(yǔ)句,返回結(jié)果三個(gè)過(guò)程
Servlet和Filter的區(qū)別:
整的流程是:Filter對(duì)用戶請(qǐng)求進(jìn)行預(yù)處理,接著將請(qǐng)求交給Servlet進(jìn)行處理并生成響應(yīng),最后Filter再對(duì)服務(wù)器響應(yīng)進(jìn)行后處理。
Filter有如下幾個(gè)用處:
Filter可以進(jìn)行對(duì)特定的url請(qǐng)求和相應(yīng)做預(yù)處理和后處理。
在HttpServletRequest到達(dá)Servlet之前,攔截客戶的HttpServletRequest。
根據(jù)需要檢查HttpServletRequest,也可以修改HttpServletRequest頭和數(shù)據(jù)。
在HttpServletResponse到達(dá)客戶端之前,攔截HttpServletResponse。
根據(jù)需要檢查HttpServletResponse,也可以修改HttpServletResponse頭和數(shù)據(jù)。
實(shí)際上Filter和Servlet極其相似,區(qū)別只是Filter不能直接對(duì)用戶生成響應(yīng)。實(shí)際上Filter里doFilter()方法里的代碼就是從多個(gè)Servlet的service()方法里抽取的通用代碼,通過(guò)使用Filter可以實(shí)現(xiàn)更好的復(fù)用。
Filter和Servlet的生命周期:
1.Filter在web服務(wù)器啟動(dòng)時(shí)初始化
2.如果某個(gè)Servlet配置了 1 ,該Servlet也是在Tomcat(Servlet容器)啟動(dòng)時(shí)初始化。
3.如果Servlet沒(méi)有配置1 ,該Servlet不會(huì)在Tomcat啟動(dòng)時(shí)初始化,而是在請(qǐng)求到來(lái)時(shí)初始化。
4.每次請(qǐng)求, Request都會(huì)被初始化,響應(yīng)請(qǐng)求后,請(qǐng)求被銷毀。
5.Servlet初始化后,將不會(huì)隨著請(qǐng)求的結(jié)束而注銷。
6.關(guān)閉Tomcat時(shí),Servlet、Filter依次被注銷。
HashMap與HashTable的區(qū)別。
1、HashMap是非線程安全的,HashTable是線程安全的。
2、HashMap的鍵和值都允許有null值存在,而HashTable則不行。
3、因?yàn)榫€程安全的問(wèn)題,HashMap效率比HashTable的要高。
HashMap的實(shí)現(xiàn)機(jī)制:
維護(hù)一個(gè)每個(gè)元素是一個(gè)鏈表的數(shù)組,而且鏈表中的每個(gè)節(jié)點(diǎn)是一個(gè)Entry[]鍵值對(duì)的數(shù)據(jù)結(jié)構(gòu)。
實(shí)現(xiàn)了數(shù)組+鏈表的特性,查找快,插入刪除也快。
對(duì)于每個(gè)key,他對(duì)應(yīng)的數(shù)組索引下標(biāo)是 int i = hash(key.hashcode)&(len-1);
每個(gè)新加入的節(jié)點(diǎn)放在鏈表首,然后該新加入的節(jié)點(diǎn)指向原鏈表首
HashMap和TreeMap區(qū)別
HashMap沖突
HashMap,ConcurrentHashMap與LinkedHashMap的區(qū)別
ConcurrentHashMap是使用了鎖分段技術(shù)技術(shù)來(lái)保證線程安全的,鎖分段技術(shù):首先將數(shù)據(jù)分成一段一段的存儲(chǔ),然后給每一段數(shù)據(jù)配一把鎖,當(dāng)一個(gè)線程占用鎖訪問(wèn)其中一個(gè)段數(shù)據(jù)的時(shí)候,其他段的數(shù)據(jù)也能被其他線程訪問(wèn)
ConcurrentHashMap 是在每個(gè)段(segment)中線程安全的
LinkedHashMap維護(hù)一個(gè)雙鏈表,可以將里面的數(shù)據(jù)按寫入的順序讀出
ConcurrentHashMap應(yīng)用場(chǎng)景
1:ConcurrentHashMap的應(yīng)用場(chǎng)景是高并發(fā),但是并不能保證線程安全,而同步的HashMap和HashMap的是鎖住整個(gè)容器,而加鎖之后ConcurrentHashMap不需要鎖住整個(gè)容器,只需要鎖住對(duì)應(yīng)的Segment就好了,所以可以保證高并發(fā)同步訪問(wèn),提升了效率。
2:可以多線程寫。
ConcurrentHashMap把HashMap分成若干個(gè)Segmenet
1.get時(shí),不加鎖,先定位到segment然后在找到頭結(jié)點(diǎn)進(jìn)行讀取操作。而value是volatile變量,所以可以保證在競(jìng)爭(zhēng)條件時(shí)保證讀取最新的值,如果讀到的value是null,則可能正在修改,那么就調(diào)用ReadValueUnderLock函數(shù),加鎖保證讀到的數(shù)據(jù)是正確的。
2.Put時(shí)會(huì)加鎖,一律添加到hash鏈的頭部。
3.Remove時(shí)也會(huì)加鎖,由于next是final類型不可改變,所以必須把刪除的節(jié)點(diǎn)之前的節(jié)點(diǎn)都復(fù)制一遍。
4.ConcurrentHashMap允許多個(gè)修改操作并發(fā)進(jìn)行,其關(guān)鍵在于使用了鎖分離技術(shù)。它使用了多個(gè)鎖來(lái)控制對(duì)Hash表的不同Segment進(jìn)行的修改。
ConcurrentHashMap的應(yīng)用場(chǎng)景是高并發(fā),但是并不能保證線程安全,而同步的HashMap和HashTable的是鎖住整個(gè)容器,而加鎖之后ConcurrentHashMap不需要鎖住整個(gè)容器,只需要鎖住對(duì)應(yīng)的segment就好了,所以可以保證高并發(fā)同步訪問(wèn),提升了效率。
ConcurrentHashMap能夠保證每一次調(diào)用都是原子操作,但是并不保證多次調(diào)用之間也是原子操作。
Vector和ArrayList的區(qū)別
ExecutorService service = Executors…. ExecutorService service = new ThreadPoolExecutor() ExecutorService service = new ScheduledThreadPoolExecutor();
ThreadPoolExecutor源碼分析
線程池本身的狀態(tài):
等待任務(wù)隊(duì)列和工作集:
線程池的主要狀態(tài)鎖:
線程池的存活時(shí)間和大?。?/p>
1.2 ThreadPoolExecutor 的內(nèi)部工作原理
有了以上定義好的數(shù)據(jù),下面來(lái)看看內(nèi)部是如何實(shí)現(xiàn)的 。 Doug Lea 的整個(gè)思路總結(jié)起來(lái)就是 5 句話:
如果當(dāng)前池大小 poolSize 小于 corePoolSize ,則創(chuàng)建新線程執(zhí)行任務(wù)。
如果當(dāng)前池大小 poolSize 大于 corePoolSize ,且等待隊(duì)列未滿,則進(jìn)入等待隊(duì)列
如果當(dāng)前池大小 poolSize 大于 corePoolSize 且小于 maximumPoolSize ,且等待隊(duì)列已滿,則創(chuàng)建新線程執(zhí)行任務(wù)。
如果當(dāng)前池大小 poolSize 大于 corePoolSize 且大于 maximumPoolSize ,且等待隊(duì)列已滿,則調(diào)用拒絕策略來(lái)處理該任務(wù)。
線程池里的每個(gè)線程執(zhí)行完任務(wù)后不會(huì)立刻退出,而是會(huì)去檢查下等待隊(duì)列里是否還有線程任務(wù)需要執(zhí)行,如果在 keepAliveTime 里等不到新的任務(wù)了,那么線程就會(huì)退出。
Executor包結(jié)構(gòu)
CopyOnWriteArrayList : 寫時(shí)加鎖,當(dāng)添加一個(gè)元素的時(shí)候,將原來(lái)的容器進(jìn)行copy,復(fù)制出一個(gè)新的容器,然后在新的容器里面寫,寫完之后再將原容器的引用指向新的容器,而讀的時(shí)候是讀舊容器的數(shù)據(jù),所以可以進(jìn)行并發(fā)的讀,但這是一種弱一致性的策略。
使用場(chǎng)景:CopyOnWriteArrayList適合使用在讀操作遠(yuǎn)遠(yuǎn)大于寫操作的場(chǎng)景里,比如緩存。
Linux常用命令:cd,cp,mv,rm,ps(進(jìn)程),tar,cat(查看內(nèi)容),chmod,vim,find,ls
死鎖的必要條件
互斥 至少有一個(gè)資源處于非共享狀態(tài)
占有并等待
非搶占
循環(huán)等待
解決死鎖,第一個(gè)是死鎖預(yù)防,就是不讓上面的四個(gè)條件同時(shí)成立。二是,合理分配資源。
三是使用銀行家算法,如果該進(jìn)程請(qǐng)求的資源操作系統(tǒng)剩余量可以滿足,那么就分配。
進(jìn)程間的通信方式
管道( pipe ):管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動(dòng),而且只能在具有親緣關(guān)系的進(jìn)程間使用。進(jìn)程的親緣關(guān)系通常是指父子進(jìn)程關(guān)系。
有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無(wú)親緣關(guān)系進(jìn)程間的通信。
信號(hào)量( semophore ) : 信號(hào)量是一個(gè)計(jì)數(shù)器,可以用來(lái)控制多個(gè)進(jìn)程對(duì)共享資源的訪問(wèn)。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問(wèn)共享資源時(shí),其他進(jìn)程也訪問(wèn)該資源。因此,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。
消息隊(duì)列( message queue ) : 消息隊(duì)列是由消息的鏈表,存放在內(nèi)核中并由消息隊(duì)列標(biāo)識(shí)符標(biāo)識(shí)。消息隊(duì)列克服了信號(hào)傳遞信息少、管道只能承載無(wú)格式字節(jié)流以及緩沖區(qū)大小受限等缺點(diǎn)。
信號(hào) ( sinal ) : 信號(hào)是一種比較復(fù)雜的通信方式,用于通知接收進(jìn)程某個(gè)事件已經(jīng)發(fā)生。
共享內(nèi)存( shared memory ) :共享內(nèi)存就是映射一段能被其他進(jìn)程所訪問(wèn)的內(nèi)存,這段共享內(nèi)存由一個(gè)進(jìn)程創(chuàng)建,但多個(gè)進(jìn)程都可以訪問(wèn)。共享內(nèi)存是最快的 IPC 方式,它是針對(duì)其他進(jìn)程間通信方式運(yùn)行效率低而專門設(shè)計(jì)的。它往往與其他通信機(jī)制,如信號(hào)量,配合使用,來(lái)實(shí)現(xiàn)進(jìn)程間的同步和通信。
套接字( socket ) : 套解口也是一種進(jìn)程間通信機(jī)制,與其他通信機(jī)制不同的是,它可用于不同機(jī)器間的進(jìn)程通信。
進(jìn)程與線程的區(qū)別和聯(lián)系
操作系統(tǒng)的進(jìn)程調(diào)度算法
計(jì)算機(jī)系統(tǒng)的層次存儲(chǔ)結(jié)構(gòu)詳解
數(shù)據(jù)庫(kù)事務(wù)是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作。
MySQL數(shù)據(jù)庫(kù)優(yōu)化總結(jié)
MYSQL 優(yōu)化常用方法
MySQL存儲(chǔ)引擎--MyISAM與InnoDB區(qū)別
關(guān)于SQL數(shù)據(jù)庫(kù)中的范式
Hibernate的一級(jí)緩存是由Session提供的,因此它只存在于Session的生命周期中,當(dāng)程序調(diào)用save(),update(),saveOrUpdate()等方法 及調(diào)用查詢接口list,filter,iterate時(shí),如Session緩存中還不存在相應(yīng)的對(duì)象,Hibernate會(huì)把該對(duì)象加入到一級(jí)緩存中,當(dāng)Session關(guān)閉的時(shí)候緩存也會(huì)消失。
Hibernate的一級(jí)緩存是Session所內(nèi)置的,不能被卸載,也不能進(jìn)行任何配置一級(jí)緩存采用的是key-value的Map方式來(lái)實(shí)現(xiàn)的,在緩存實(shí)體對(duì)象時(shí),對(duì)象的主關(guān)鍵字ID是Map的key,實(shí)體對(duì)象就是對(duì)應(yīng)的值。
Hibernate二級(jí)緩存:把獲得的所有數(shù)據(jù)對(duì)象根據(jù)ID放入到第二級(jí)緩存中。Hibernate二級(jí)緩存策略,是針對(duì)于ID查詢的緩存策略,刪除、更新、增加數(shù)據(jù)的時(shí)候,同時(shí)更新緩存。
進(jìn)程和線程的區(qū)別:
進(jìn)程:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開銷,一個(gè)進(jìn)程包含1–n個(gè)線程。
線程:同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程切換開銷小。
線程和進(jìn)程一樣分為五個(gè)階段:創(chuàng)建、就緒、運(yùn)行、阻塞、終止。
多進(jìn)程是指操作系統(tǒng)能同時(shí)運(yùn)行多個(gè)任務(wù)(程序)。
多線程是指在同一程序中有多個(gè)順序流在執(zhí)行。
在java中要想實(shí)現(xiàn)多線程,有三種手段,一種是繼續(xù)Thread類,另外一種是實(shí)現(xiàn)Runable接口,還有就是實(shí)現(xiàn)Callable接口。
Switch能否用string做參數(shù)?
a.在 Java 7 之前, switch 只能支持byte,short,char,int 或者其對(duì)應(yīng)的封裝類以及 Enum 類型。在Java 7中,String 支持被加上了。
Object有哪些公用方法?
a.方法equals測(cè)試的是兩個(gè)對(duì)象是否相等
b.方法clone進(jìn)行對(duì)象拷貝
c.方法getClass返回和當(dāng)前對(duì)象相關(guān)的Class對(duì)象
d.方法notify,notifyall,wait都是用來(lái)對(duì)給定對(duì)象進(jìn)行線程同步的
Java的四種引用,強(qiáng)弱軟虛,以及用到的場(chǎng)景
a.利用軟引用和弱引用解決OOM問(wèn)題:用一個(gè)HashMap來(lái)保存圖片的路徑和相應(yīng)圖片對(duì)象關(guān)聯(lián)的軟引用之間的映射關(guān)系,在內(nèi)存不足時(shí),JVM會(huì)自動(dòng)回收這些緩存圖片對(duì)象所占用的空間,從而有效地避免了OOM的問(wèn)題。
b.通過(guò)軟可及對(duì)象重獲方法實(shí)現(xiàn)Java對(duì)象的高速緩存:比如我們創(chuàng)建了一Employee的類,如果每次需要查詢一個(gè)雇員的信息。哪怕是幾秒中之前剛剛查詢過(guò)的,都要重新構(gòu)建一個(gè)實(shí)例,這是需要消耗很多時(shí)間的。我們可以通過(guò)軟引用和 HashMap 的結(jié)合,先是保存引用方面:以軟引用的方式對(duì)一個(gè)Employee對(duì)象的實(shí)例進(jìn)行引用并保存該引用到HashMap 上,key 為此雇員的 id,value為這個(gè)對(duì)象的軟引用,另一方面是取出引用,緩存中是否有該Employee實(shí)例的軟引用,如果有,從軟引用中取得。如果沒(méi)有軟引用,或者從軟引用中得到的實(shí)例是null,重新構(gòu)建一個(gè)實(shí)例,并保存對(duì)這個(gè)新建實(shí)例的軟引用。
c.強(qiáng)引用:如果一個(gè)對(duì)象具有強(qiáng)引用,它就不會(huì)被垃圾回收器回收。即使當(dāng)前內(nèi)存空間不足,JVM也不會(huì)回收它,而是拋出 OutOfMemoryError 錯(cuò)誤,使程序異常終止。如果想中斷強(qiáng)引用和某個(gè)對(duì)象之間的關(guān)聯(lián),可以顯式地將引用賦值為null,這樣一來(lái)的話,JVM在合適的時(shí)間就會(huì)回收該對(duì)象。
d.軟引用:在使用軟引用時(shí),如果內(nèi)存的空間足夠,軟引用就能繼續(xù)被使用,而不會(huì)被垃圾回收器回收,只有在內(nèi)存不足時(shí),軟引用才會(huì)被垃圾回收器回收。
e.弱引用:具有弱引用的對(duì)象擁有的生命周期更短暫。因?yàn)楫?dāng) JVM 進(jìn)行垃圾回收,一旦發(fā)現(xiàn)弱引用對(duì)象,無(wú)論當(dāng)前內(nèi)存空間是否充足,都會(huì)將弱引用回收。不過(guò)由于垃圾回收器是一個(gè)優(yōu)先級(jí)較低的線程,所以并不一定能迅速發(fā)現(xiàn)弱引用對(duì)象。
f.虛引用:顧名思義,就是形同虛設(shè),如果一個(gè)對(duì)象僅持有虛引用,那么它相當(dāng)于沒(méi)有引用,在任何時(shí)候都可能被垃圾回收器回收。
Hashcode的作用,與 equal 有什么區(qū)別?
a.同樣用于鑒定2個(gè)對(duì)象是否相等的,java集合中有 list 和 set 兩類,其中 set不允許元素重復(fù)實(shí)現(xiàn),那個(gè)這個(gè)不允許重復(fù)實(shí)現(xiàn)的方法,如果用 equal 去比較的話,如果存在1000個(gè)元素,你 new 一個(gè)新的元素出來(lái),需要去調(diào)用1000次 equal 去逐個(gè)和他們比較是否是同一個(gè)對(duì)象,這樣會(huì)大大降低效率。hashcode實(shí)際上是返回對(duì)象的存儲(chǔ)地址,如果這個(gè)位置上沒(méi)有元素,就把元素直接存儲(chǔ)在上面,如果這個(gè)位置上已經(jīng)存在元素,這個(gè)時(shí)候才去調(diào)用equal方法與新元素進(jìn)行比較,相同的話就不存了,散列到其他地址上。
Override和Overload的含義以及區(qū)別
a.Overload顧名思義是重新加載,它可以表現(xiàn)類的多態(tài)性,可以是函數(shù)里面可以有相同的函數(shù)名但是參數(shù)名、返回值、類型不能相同;或者說(shuō)可以改變參數(shù)、類型、返回值但是函數(shù)名字依然不變。
b.就是ride(重寫)的意思,在子類繼承父類的時(shí)候子類中可以定義某方法與其父類有相同的名稱和參數(shù),當(dāng)子類在調(diào)用這一函數(shù)時(shí)自動(dòng)調(diào)用子類的方法,而父類相當(dāng)于被覆蓋(重寫)了。
具體可前往C++中重載、重寫(覆蓋)的區(qū)別實(shí)例分析查看
抽象類和接口的區(qū)別
a.一個(gè)類只能繼承單個(gè)類,但是可以實(shí)現(xiàn)多個(gè)接口
b.抽象類中可以有構(gòu)造方法,接口中不能有構(gòu)造方法
c.抽象類中的所有方法并不一定要是抽象的,你可以選擇在抽象類中實(shí)現(xiàn)一些基本的方法。而接口要求所有的方法都必須是抽象的
d.抽象類中可以包含靜態(tài)方法,接口中不可以
e.抽象類中可以有普通成員變量,接口中不可以
解析XML的幾種方式的原理與特點(diǎn):DOM、SAX、PULL
a.DOM:消耗內(nèi)存:先把xml文檔都讀到內(nèi)存中,然后再用DOM API來(lái)訪問(wèn)樹形結(jié)構(gòu),并獲取數(shù)據(jù)。這個(gè)寫起來(lái)很簡(jiǎn)單,但是很消耗內(nèi)存。要是數(shù)據(jù)過(guò)大,手機(jī)不夠牛逼,可能手機(jī)直接死機(jī)
b.SAX:解析效率高,占用內(nèi)存少,基于事件驅(qū)動(dòng)的:更加簡(jiǎn)單地說(shuō)就是對(duì)文檔進(jìn)行順序掃描,當(dāng)掃描到文檔(document)開始與結(jié)束、元素(element)開始與結(jié)束、文檔(document)結(jié)束等地方時(shí)通知事件處理函數(shù),由事件處理函數(shù)做相應(yīng)動(dòng)作,然后繼續(xù)同樣的掃描,直至文檔結(jié)束。
c.PULL:與 SAX 類似,也是基于事件驅(qū)動(dòng),我們可以調(diào)用它的next()方法,來(lái)獲取下一個(gè)解析事件(就是開始文檔,結(jié)束文檔,開始標(biāo)簽,結(jié)束標(biāo)簽),當(dāng)處于某個(gè)元素時(shí)可以調(diào)用XmlPullParser的getAttributte()方法來(lái)獲取屬性的值,也可調(diào)用它的nextText()獲取本節(jié)點(diǎn)的值。
wait()和sleep()的區(qū)別
sleep來(lái)自Thread類,和wait來(lái)自O(shè)bject類
調(diào)用sleep()方法的過(guò)程中,線程不會(huì)釋放對(duì)象鎖。而 調(diào)用 wait 方法線程會(huì)釋放對(duì)象鎖
sleep睡眠后不出讓系統(tǒng)資源,wait讓出系統(tǒng)資源其他線程可以占用CPU
sleep(milliseconds)需要指定一個(gè)睡眠時(shí)間,時(shí)間一到會(huì)自動(dòng)喚醒
JAVA 中堆和棧的區(qū)別,說(shuō)下java 的內(nèi)存機(jī)制
a.基本數(shù)據(jù)類型比變量和對(duì)象的引用都是在棧分配的
b.堆內(nèi)存用來(lái)存放由new創(chuàng)建的對(duì)象和數(shù)組
c.類變量(static修飾的變量),程序在一加載的時(shí)候就在堆中為類變量分配內(nèi)存,堆中的內(nèi)存地址存放在棧中
d.實(shí)例變量:當(dāng)你使用java關(guān)鍵字new的時(shí)候,系統(tǒng)在堆中開辟并不一定是連續(xù)的空間分配給變量,是根據(jù)零散的堆內(nèi)存地址,通過(guò)哈希算法換算為一長(zhǎng)串?dāng)?shù)字以表征這個(gè)變量在堆中的”物理位置”,實(shí)例變量的生命周期–當(dāng)實(shí)例變量的引用丟失后,將被GC(垃圾回收器)列入可回收“名單”中,但并不是馬上就釋放堆中內(nèi)存
e.局部變量: 由聲明在某方法,或某代碼段里(比如for循環(huán)),執(zhí)行到它的時(shí)候在棧中開辟內(nèi)存,當(dāng)局部變量一但脫離作用域,內(nèi)存立即釋放
JAVA多態(tài)的實(shí)現(xiàn)原理
a.抽象的來(lái)講,多態(tài)的意思就是同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式。(發(fā)送消息就是函數(shù)調(diào)用)
b.實(shí)現(xiàn)的原理是動(dòng)態(tài)綁定,程序調(diào)用的方法在運(yùn)行期才動(dòng)態(tài)綁定,追溯源碼可以發(fā)現(xiàn),JVM 通過(guò)參數(shù)的自動(dòng)轉(zhuǎn)型來(lái)找到合適的辦法。
相關(guān)推薦:
Atas ialah kandungan terperinci 各大公司Java面試題歸納整理(全). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Sebagai bahasa pengaturcaraan yang telah menjadi sangat popular sejak beberapa tahun kebelakangan ini, bahasa Go telah menjadi tempat hangat untuk temu duga di banyak syarikat dan perusahaan. Bagi pemula bahasa Go, cara menjawab soalan yang berkaitan semasa proses temu duga adalah soalan yang patut diterokai. Berikut ialah lima soalan dan jawapan temuduga bahasa Go yang biasa untuk rujukan pemula. Sila perkenalkan bagaimana mekanisme pengumpulan sampah bahasa Go berfungsi? Mekanisme pengumpulan sampah bahasa Go adalah berdasarkan algoritma sapu tanda dan algoritma penandaan tiga warna. Apabila ruang memori dalam program Go tidak mencukupi, pengumpul sampah Go

php中文網(wǎng)作為知名編程學(xué)習(xí)網(wǎng)站,為您整理了一些React面試題,幫助前端開發(fā)人員準(zhǔn)備和清除React面試障礙。

本篇文章給大家總結(jié)一些值得收藏的精選Web前端面試題(附答案)。有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)大家有所幫助。

Artikel ini akan berkongsi dengan anda 50 soalan temuduga sudut yang anda mesti kuasai. Ia akan menganalisis 50 soalan temu bual ini daripada tiga bahagian: pemula, pertengahan dan lanjutan, dan membantu anda memahaminya dengan teliti!

Artikel ini meringkaskan untuk anda beberapa soalan temu duga frekuensi tinggi vue terpilih pada tahun 2023 (dengan jawapan) yang patut dikumpul. Ia mempunyai nilai rujukan tertentu Rakan-rakan yang memerlukan boleh merujuk kepadanya.

Keselarasan tinggi adalah pengalaman yang hampir setiap pengaturcara mahu miliki. Sebabnya mudah: apabila trafik meningkat, kami akan menghadapi pelbagai masalah teknikal, seperti tamat masa tindak balas antara muka, beban CPU yang meningkat, GC yang kerap, kebuntuan, storan data yang besar, dll. Masalah ini boleh menggalakkan kami dalam peningkatan berterusan dalam kedalaman teknikal.

Baru minggu lepas, rakan sekelas ditanya soalan ini semasa temu bual teknikal dengan Alibaba Cloud: Dengan mengandaikan platform dengan 1 juta permintaan log masuk setiap hari dan nod perkhidmatan dengan memori 8G, bagaimana untuk menetapkan parameter JVM? Jika anda rasa jawapannya tidak sesuai, datang dan tanya saya untuk semakan.

Artikel ini menyusun dan berkongsi 28 soalan temuduga PHP (dengan jawapan untuk dikongsi) untuk membantu anda menyusun pengetahuan asas Ia mempunyai nilai rujukan tertentu. Saya harap ia akan membantu semua orang.
