- 相關(guān)推薦
最新2017阿里巴巴招聘筆試題
以下是CN人才網(wǎng)小編為大家整理的最新2017阿里巴巴招聘筆試題,歡迎閱讀參考。
1、多線程什么情況下執(zhí)行wait?
答:在同步代碼塊中,即對(duì)象只有獲得了互斥鎖之后才可以調(diào)用wait()方法。
延伸學(xué)習(xí)(1):
sleep( )和wait( n)、wait( )的區(qū)別:
sleep方法:是Thread類(lèi)的靜態(tài)方法,當(dāng)前線程將睡眠n毫秒,線程進(jìn)入阻塞狀態(tài)。當(dāng)睡眠時(shí)間到了,會(huì)解除阻塞,進(jìn)行可運(yùn)行狀態(tài),等待CPU的到來(lái)。睡眠不釋放鎖(如果有的話)
wait方法:是Object的方法,必須與synchronized關(guān)鍵字一起使用,線程進(jìn)入阻塞狀態(tài),當(dāng)notify或者notifyall被調(diào)用后,會(huì)解除阻塞。但是,只有重新占用互斥鎖之后才會(huì)進(jìn)入可運(yùn)行狀態(tài)。睡眠時(shí),釋放互斥鎖。
join( )方法:
當(dāng)前線程調(diào)用,則其它線程全部停止,等待當(dāng)前線程執(zhí)行完畢,接著執(zhí)行。
suspend( )和resume( )方法:
兩個(gè)方法配套使用,前者使線程進(jìn)入阻塞狀態(tài),并且不會(huì)自動(dòng)恢復(fù),必須等待resume( )方法被調(diào)用,才能使得線程重新進(jìn)入可執(zhí)行狀態(tài)。
典型用法,用于等待另一個(gè)線程產(chǎn)生的結(jié)果的情形,測(cè)試發(fā)現(xiàn)結(jié)果還沒(méi)有產(chǎn)生后,讓線程阻塞。當(dāng)另一個(gè)線程產(chǎn)生了結(jié)果后,調(diào)用resume( )使其恢復(fù)。
yield() 方法:
yield() 使得線程放棄當(dāng)前分得的 CPU 時(shí)間,但是不使線程阻塞,即線程仍處于可執(zhí)行狀態(tài),隨時(shí)可能再次分得 CPU 時(shí)間。調(diào)用 yield() 的效果等價(jià)于調(diào)度程序認(rèn)為該線程已執(zhí)行了足夠的時(shí)間從而轉(zhuǎn)到另一個(gè)線程。
延伸學(xué)習(xí)(2):
線程的的生命周期:創(chuàng)建狀態(tài)、就緒狀態(tài)(可運(yùn)行狀態(tài))、運(yùn)行狀態(tài)、阻塞狀態(tài)、消亡狀態(tài)。
2、Spring容器如何加載?
答:
在應(yīng)用程序web.xml中做了以下配置信息時(shí),當(dāng)啟動(dòng)Web容器時(shí)就會(huì)自動(dòng)加載spring容器。
ContextLoaderListener!!!
org.springframework.web.context.ContextLoaderListener
[html] view plain copy
org.springframework.web.context.ContextLoaderListener
ContextLoaderListener類(lèi)實(shí)現(xiàn)了javax.servlet.ServletContextListener接口并且繼承了org.springframework.web.context.ContextLoader類(lèi)。
ServletContextListener事件類(lèi)是Web容器的一部分,處理Web應(yīng)用的Servlet上下文(context)的監(jiān)聽(tīng)。實(shí)現(xiàn)ServletContextListener接口中的contextInitialized和contextDestroyed方法。當(dāng)Web容器啟動(dòng)時(shí)會(huì)自動(dòng)調(diào)用contextInitialized方法,進(jìn)行初始化Spring Web應(yīng)用程序上下文,主要加載web.xml中contextConfigLocation的配置文件;當(dāng)Web容器關(guān)閉之前會(huì)調(diào)用contextDestroyed方法,進(jìn)行銷(xiāo)毀Spring Web應(yīng)用程序上下文。ContextLoader類(lèi)實(shí)現(xiàn)了Spring上下文初始化的工作,執(zhí)行initWebApplicationContext方法返回WebApplicationContext。
延伸學(xué)習(xí):
如果要spring-mvc的話,需要在web.xml文件中配置如下:
DispatchServlet!!!
org.springframework.web.servlet.DispatchServlet
[html] view plain copy
simpleSpringMVC/servlet-name>
org.springframework.web.servlet.DispatchServlet
1
simpleSpringMVC
*.htm
3、Servlet生命周期(什么時(shí)候destory)?
答:Servlet的生命周期是由Servlet容器(即Web服務(wù)器)來(lái)控制的,通過(guò)簡(jiǎn)單的概括可以分為4步:
(1)Servlet類(lèi)加載
(2)實(shí)例化Servlet
(3)Servlet提供服務(wù)
(4)銷(xiāo)毀Servlet
當(dāng)Web應(yīng)用被終止時(shí),Servlet容器會(huì)先調(diào)用Web應(yīng)用中所有的Servlet對(duì)象的destroy( )方法,然后再銷(xiāo)毀Servlet對(duì)象。
4、10G數(shù)據(jù),每一條是一個(gè)qq號(hào),統(tǒng)計(jì)出現(xiàn)頻率最多的qq號(hào)。
答:
首先你要注意到,數(shù)據(jù)存在服務(wù)器,存儲(chǔ)不了(內(nèi)存存不了),要想辦法統(tǒng)計(jì)每一個(gè)qq出現(xiàn)的次數(shù)。
比如,因?yàn)閮?nèi)存是1g,首先 你用hash 的方法,把qq分配到10個(gè)(這個(gè)數(shù)字可以變動(dòng),比較)文件(在硬盤(pán)中)。
相同的qq肯定在同一個(gè)文件中,然后對(duì)每一個(gè)文件,只要保證每一個(gè)文件少于1g的內(nèi)存,統(tǒng)計(jì)每個(gè)qq的次數(shù),可以使用hash_map(qq, qq_count)實(shí)現(xiàn)。然后,記錄每個(gè)文件的最大訪問(wèn)次數(shù)的qq,最后,從10個(gè)文件中找出一個(gè)最大,即為所有的最大。
那若面試官問(wèn)有沒(méi)有更高效率的解法之類(lèi)的?這時(shí),你可以?xún)?yōu)化一下,但是這個(gè)速度很快,hash函數(shù),速度很快,他肯定會(huì)問(wèn),你如何設(shè)計(jì),用bitmap也行。
5、hashmap實(shí)現(xiàn)原理
HashMap解決hash沖突的過(guò)程如下:
HashMap 采用一種所謂的“Hash 算法”來(lái)決定每個(gè)元素的存儲(chǔ)位置。當(dāng)程序執(zhí)行 map.put(String,Obect)方法 時(shí),系統(tǒng)將調(diào)用String的 hashCode() 方法得到其 hashCode 值——每個(gè) Java 對(duì)象都有 hashCode() 方法,都可通過(guò)該方法獲得它的 hashCode 值。得到這個(gè)對(duì)象的 hashCode 值之后,系統(tǒng)會(huì)根據(jù)該 hashCode 值來(lái)決定該元素的存儲(chǔ)位置。源碼如下:
[java] view plain copy
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry e = table[i]; e != null; e = e.next) {
Object k;
//判斷當(dāng)前確定的索引位置是否存在相同hashcode和相同key的元素,如果存在相同的hashcode和相同的key的元素,那么新值覆蓋原來(lái)的舊值,并返回舊值。
//如果存在相同的hashcode,那么他們確定的索引位置就相同,這時(shí)判斷他們的key是否相同,如果不相同,這時(shí)就是產(chǎn)生了hash沖突。
//Hash沖突后,那么HashMap的單個(gè)bucket里存儲(chǔ)的不是一個(gè) Entry,而是一個(gè) Entry 鏈。
//系統(tǒng)只能必須按順序遍歷每個(gè) Entry,直到找到想搜索的 Entry 為止——如果恰好要搜索的 Entry 位于該 Entry 鏈的最末端(該 Entry 是最早放入該 bucket 中),
//那系統(tǒng)必須循環(huán)到最后才能找到該元素。
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
上面程序中用到了一個(gè)重要的內(nèi)部接口:Map.Entry,每個(gè) Map.Entry 其實(shí)就是一個(gè) key-value 對(duì)。從上面程序中可以看出:當(dāng)系統(tǒng)決定存儲(chǔ) HashMap 中的 key-value 對(duì)時(shí),完全沒(méi)有考慮 Entry 中的 value,僅僅只是根據(jù) key 來(lái)計(jì)算并決定每個(gè) Entry 的存儲(chǔ)位置。這也說(shuō)明了前面的結(jié)論:我們完全可以把 Map 集合中的 value 當(dāng)成 key 的附屬,當(dāng)系統(tǒng)決定了 key 的存儲(chǔ)位置之后,value 隨之保存在那里即可.HashMap程序經(jīng)過(guò)我改造,我故意的構(gòu)造出了hash沖突現(xiàn)象,因?yàn)镠ashMap的初始大小16,但是我在hashmap里面放了超過(guò)16個(gè)元素,并且我屏蔽了它的resize()方法。不讓它去擴(kuò)容。這時(shí)HashMap的底層數(shù)組Entry[] table結(jié)構(gòu)如下:
Hashmap里面的bucket出現(xiàn)了單鏈表的形式,散列表要解決的一個(gè)問(wèn)題就是散列值的沖突問(wèn)題,通常是兩種方法:鏈表法和開(kāi)放地址法。鏈表法就是將相同hash值的對(duì)象組織成一個(gè)鏈表放在hash值對(duì)應(yīng)的槽位;開(kāi)放地址法是通過(guò)一個(gè)探測(cè)算法,當(dāng)某個(gè)槽位已經(jīng)被占據(jù)的情況下繼續(xù)查找下一個(gè)可以使用的槽位。java.util.HashMap采用的鏈表法的方式,鏈表是單向鏈表。形成單鏈表的核心代碼如下:
[java] view plain copy
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry e = table[bucketIndex];
table[bucketIndex] = new Entry(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
上面方法的代碼很簡(jiǎn)單,但其中包含了一個(gè)設(shè)計(jì):系統(tǒng)總是將新添加的 Entry 對(duì)象放入 table 數(shù)組的 bucketIndex 索引處——如果 bucketIndex 索引處已經(jīng)有了一個(gè) Entry 對(duì)象,那新添加的 Entry 對(duì)象指向原有的 Entry 對(duì)象(產(chǎn)生一個(gè) Entry 鏈),如果 bucketIndex 索引處沒(méi)有 Entry 對(duì)象,也就是上面程序代碼的 e 變量是 null,也就是新放入的 Entry 對(duì)象指向 null,也就是沒(méi)有產(chǎn)生 Entry 鏈。
HashMap里面沒(méi)有出現(xiàn)hash沖突時(shí),沒(méi)有形成單鏈表時(shí),hashmap查找元素很快,get()方法能夠直接定位到元素,但是出現(xiàn)單鏈表后,單個(gè)bucket 里存儲(chǔ)的不是一個(gè) Entry,而是一個(gè) Entry 鏈,系統(tǒng)只能必須按順序遍歷每個(gè) Entry,直到找到想搜索的 Entry 為止——如果恰好要搜索的 Entry 位于該 Entry 鏈的最末端(該 Entry 是最早放入該 bucket 中),那系統(tǒng)必須循環(huán)到最后才能找到該元素。
當(dāng)創(chuàng)建 HashMap 時(shí),有一個(gè)默認(rèn)的負(fù)載因子(load factor),其默認(rèn)值為 0.75,這是時(shí)間和空間成本上一種折衷:增大負(fù)載因子可以減少 Hash 表(就是那個(gè) Entry 數(shù)組)所占用的內(nèi)存空間,但會(huì)增加查詢(xún)數(shù)據(jù)的時(shí)間開(kāi)銷(xiāo),而查詢(xún)是最頻繁的的操作(HashMap 的 get() 與 put() 方法都要用到查詢(xún));減小負(fù)載因子會(huì)提高數(shù)據(jù)查詢(xún)的性能,但會(huì)增加 Hash 表所占用的內(nèi)存空間。
6、數(shù)組和鏈表的比較
答:
數(shù)組靜態(tài)分配內(nèi)存,鏈表動(dòng)態(tài)分配內(nèi)存;
數(shù)組在內(nèi)存中連續(xù),鏈表不連續(xù);
數(shù)組元素在棧區(qū),鏈表元素在堆區(qū);
數(shù)組利用下標(biāo)定位,時(shí)間復(fù)雜度為O(1),鏈表定位元素時(shí)間復(fù)雜度O(n);
數(shù)組插入或刪除元素的時(shí)間復(fù)雜度O(n),鏈表的時(shí)間復(fù)雜度O(1)。
7、ArrayList和Linkedlist對(duì)比
答:
ArrayList和LinkedList在性能上各有優(yōu)缺點(diǎn),都有各自所適用的地方,總的說(shuō)來(lái)可以描述如下:
1.對(duì)ArrayList和LinkedList而言,在列表末尾增加一個(gè)元素所花的開(kāi)銷(xiāo)都是固定的。對(duì)ArrayList而言,主要是在內(nèi)部數(shù)組中增加一項(xiàng),指向所添加的元素,偶爾可能會(huì)導(dǎo)致對(duì)數(shù)組重新進(jìn)行分配;而對(duì)LinkedList而言,這個(gè)開(kāi)銷(xiāo)是統(tǒng)一的,分配一個(gè)內(nèi)部Entry對(duì)象。
2.在ArrayList的中間插入或刪除一個(gè)元素意味著這個(gè)列表中剩余的元素都會(huì)被移動(dòng);而在LinkedList的中間插入或刪除一個(gè)元素的開(kāi)銷(xiāo)是固定的。
3.LinkedList不支持高效的隨機(jī)元素訪問(wèn)。
4.ArrayList的空間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗相當(dāng)?shù)目臻g
可以這樣說(shuō):當(dāng)操作是在一列數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問(wèn)其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能;當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù),并且按照順序訪問(wèn)其中的元素時(shí),就應(yīng)該使用LinkedList了。
程序員們,你答對(duì)了幾題,有實(shí)力進(jìn)入阿里巴巴嗎?可以留言與我們討論哦!
【最新阿里巴巴招聘筆試題】相關(guān)文章:
醫(yī)院招聘護(hù)士常見(jiàn)考試題目05-11
幼兒教師招聘考試題庫(kù)09-13
最新防災(zāi)減災(zāi)知識(shí)測(cè)試題04-26
最新的抖音主播簡(jiǎn)短的招聘文案11-16
最新公共場(chǎng)所從業(yè)人員衛(wèi)生知識(shí)培訓(xùn)試題08-10
英語(yǔ)試題08-17
最新英語(yǔ)CET4聽(tīng)力試題練習(xí)(通用5篇)03-18
成人高考高升專(zhuān)《語(yǔ)文》模擬試題試題11-12
招聘實(shí)習(xí)總結(jié)08-22
招聘簡(jiǎn)歷模板10-30