這些面試題是我在今年年初換工作的時(shí)候整理,沒有重點(diǎn)尿扯。包括java基礎(chǔ)求晶,數(shù)據(jù)結(jié)構(gòu),網(wǎng)絡(luò)衷笋,Android相關(guān)等等芳杏。適合中高級(jí)工程師。由于內(nèi)容過多,將會(huì)分為上下兩部分蚜锨。下部分跳轉(zhuǎn)鏈接:http://www.cnblogs.com/huangjialin/p/8657696.html
希望能夠幫到一些朋友档插,如果幫助到你,希望能夠點(diǎn)個(gè)贊亚再。沒有單獨(dú)分出來郭膛,面試題目都是穿插的。因?yàn)橛行┦峦饷嬖囘^程中遇到的氛悬,我就又加上去了则剃。總之你弄懂了這些如捅,基本是沒有問題了棍现。如果是bat那些企業(yè),你還得準(zhǔn)備算法镜遣,jvm這些知識(shí)己肮。好了,廢話不多說了悲关。
1谎僻、java中==和equals和hashCode的區(qū)別?
基本數(shù)據(jù)類型的==比較的值相等.
類的==比較的內(nèi)存的地址,即是否是同一個(gè)對(duì)象寓辱,在不覆蓋equals的情況下艘绍,同比較內(nèi)存地址,原實(shí)現(xiàn)也為 == 秫筏,如String等重寫了equals方法.
hashCode也是Object類的一個(gè)方法诱鞠。返回一個(gè)離散的int型整數(shù)。在集合類操作中使用这敬,為了提高查詢速度航夺。(HashMap,HashSet等比較是否為同一個(gè))
如果兩個(gè)對(duì)象equals鹅颊,Java運(yùn)行時(shí)環(huán)境會(huì)認(rèn)為他們的hashcode一定相等敷存。
如果兩個(gè)對(duì)象不equals,他們的hashcode有可能相等堪伍。
如果兩個(gè)對(duì)象hashcode相等,他們不一定equals觅闽。
如果兩個(gè)對(duì)象hashcode不相等帝雇,他們一定不equals。
2蛉拙、int與integer的區(qū)別?
int 基本類型
integer 對(duì)象 int的封裝類
3尸闸、String、StringBuffer、StringBuilder區(qū)別?
String:字符串常量 不適用于經(jīng)常要改變值得情況吮廉,每次改變相當(dāng)于生成一個(gè)新的對(duì)象
StringBuffer:字符串變量 (線程安全)
StringBuilder:字符串變量(線程不安全) 確保單線程下可用苞尝,效率略高于StringBuffer
4、什么是內(nèi)部類宦芦?內(nèi)部類的作用?
內(nèi)部類可直接訪問外部類的屬性
Java中內(nèi)部類主要分為成員內(nèi)部類宙址、局部內(nèi)部類(嵌套在方法和作用域內(nèi))、匿名內(nèi)部類(沒構(gòu)造方法)调卑、靜態(tài)內(nèi)部類(static修飾的類抡砂,不能使用任何外圍類的非static成員變量和方法, 不依賴外圍類)
5恬涧、進(jìn)程和線程的區(qū)別?
進(jìn)程是cpu資源分配的最小單位注益,線程是cpu調(diào)度的最小單位。
進(jìn)程之間不能共享資源溯捆,而線程共享所在進(jìn)程的地址空間和其它資源丑搔。
一個(gè)進(jìn)程內(nèi)可擁有多個(gè)線程,進(jìn)程可開啟進(jìn)程提揍,也可開啟線程低匙。
一個(gè)線程只能屬于一個(gè)進(jìn)程,線程可直接使用同進(jìn)程的資源,線程依賴于進(jìn)程而存在碳锈。
6顽冶、final,finally售碳,finalize的區(qū)別?
final:修飾類强重、成員變量和成員方法,類不可被繼承贸人,成員變量不可變间景,成員方法不可重寫
finally:與try...catch...共同使用,確保無論是否出現(xiàn)異常都能被調(diào)用到
finalize:類的方法,垃圾回收之前會(huì)調(diào)用此方法,子類可以重寫finalize()方法實(shí)現(xiàn)對(duì)資源的回收
7艺智、Serializable?和Parcelable?的區(qū)別?
Serializable Java 序列化接口 在硬盤上讀寫 讀寫過程中有大量臨時(shí)變量的生成倘要,內(nèi)部執(zhí)行大量的i/o操作,效率很低十拣。
Parcelable Android 序列化接口 效率高 使用麻煩 在內(nèi)存中讀寫(AS有相關(guān)插件 一鍵生成所需方法)?封拧,對(duì)象不能保存到磁盤中
8、靜態(tài)屬性和靜態(tài)方法是否可以被繼承夭问?是否可以被重寫泽西?以及原因?
可繼承 不可重寫 而是被隱藏
如果子類里面定義了靜態(tài)方法和屬性缰趋,那么這時(shí)候父類的靜態(tài)方法或?qū)傩苑Q之為"隱藏"捧杉。如果你想要調(diào)用父類的靜態(tài)方法和屬性陕见,直接通過父類名.方法或變量名完成。
9味抖、成員內(nèi)部類评甜、靜態(tài)內(nèi)部類、局部內(nèi)部類和匿名內(nèi)部類的理解仔涩,以及項(xiàng)目中的應(yīng)用
ava中內(nèi)部類主要分為成員內(nèi)部類忍坷、局部內(nèi)部類(嵌套在方法和作用域內(nèi))、匿名內(nèi)部類(沒構(gòu)造方法)红柱、靜態(tài)內(nèi)部類(static修飾的類承匣,不能使用任何外圍類的非static成員變量和方法, 不依賴外圍類)
使用內(nèi)部類最吸引人的原因是:每個(gè)內(nèi)部類都能獨(dú)立地繼承一個(gè)(接口的)實(shí)現(xiàn)锤悄,所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn)韧骗,對(duì)于內(nèi)部類都沒有影響。
因?yàn)镴ava不支持多繼承零聚,支持實(shí)現(xiàn)多個(gè)接口袍暴。但有時(shí)候會(huì)存在一些使用接口很難解決的問題,這個(gè)時(shí)候我們可以利用內(nèi)部類提供的隶症、可以繼承多個(gè)具體的或者抽象的類的能力來解決這些程序設(shè)計(jì)問題政模×苎可以這樣說胁住,接口只是解決了部分問題,而內(nèi)部類使得多重繼承的解決方案變得更加完整儡司。
10、string?轉(zhuǎn)換成?integer的方式及原理
String ?integer ? Intrger.parseInt(string);
Integer?string? ? Integer.toString();
11余指、哪些情況下的對(duì)象會(huì)被垃圾回收機(jī)制處理掉捕犬?
1.所有實(shí)例都沒有活動(dòng)線程訪問。
2.沒有被其他任何實(shí)例訪問的循環(huán)引用實(shí)例酵镜。?
3.Java 中有不同的引用類型碉碉。判斷實(shí)例是否符合垃圾收集的條件都依賴于它的引用類型。?
要判斷怎樣的對(duì)象是沒用的對(duì)象笋婿。這里有2種方法:
1.采用標(biāo)記計(jì)數(shù)的方法:
給內(nèi)存中的對(duì)象給打上標(biāo)記誉裆,對(duì)象被引用一次,計(jì)數(shù)就加1缸濒,引用被釋放了足丢,計(jì)數(shù)就減一,當(dāng)這個(gè)計(jì)數(shù)為0的時(shí)候庇配,這個(gè)對(duì)象就可以被回收了斩跌。當(dāng)然,這也就引發(fā)了一個(gè)問題:循環(huán)引用的對(duì)象是無法被識(shí)別出來并且被回收的捞慌。所以就有了第二種方法:
2.采用根搜索算法:
從一個(gè)根出發(fā)耀鸦,搜索所有的可達(dá)對(duì)象,這樣剩下的那些對(duì)象就是需要被回收的
12啸澡、靜態(tài)代理和動(dòng)態(tài)代理的區(qū)別袖订,什么場景使用洛姑?
靜態(tài)代理類:
?? ? 由程序員創(chuàng)建或由特定工具自動(dòng)生成源代碼,再對(duì)其編譯硫眯。在程序運(yùn)行前,代理類的.class文件就已經(jīng)存在了裹纳。動(dòng)態(tài)代理類:在程序運(yùn)行時(shí)痊夭,運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成她我。
14番舆、Java中實(shí)現(xiàn)多態(tài)的機(jī)制是什么?
答:方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)
重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn)
重載Overloading是一個(gè)類中多態(tài)性的一種表現(xiàn).
16禾怠、說說你對(duì)Java反射的理解
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中, 對(duì)于任意一個(gè)類, 都能夠知道這個(gè)類的所有屬性和方法; 對(duì)于任意一個(gè)對(duì)象, 都能夠調(diào)用它的任意一個(gè)方法和屬性芽偏。? ? ? ? 從對(duì)象出發(fā)污尉,通過反射(Class類)可以取得取得類的完整信息(類名 Class類型,所在包锐朴、具有的所有方法 Method[]類型、某個(gè)方法的完整信息(包括修飾符娩嚼、返回值類型、異常贵少、參數(shù)類型)、所有屬性 Field[]录平、某個(gè)屬性的完整信息、構(gòu)造器 Constructors)表箭,調(diào)用類的屬性或方法自己的總結(jié): 在運(yùn)行過程中獲得類彼水、對(duì)象握童、方法的所有信息澡绩。
17溪掀、說說你對(duì)Java注解的理解?
元注解
元注解的作用就是負(fù)責(zé)注解其他注解。java5.0的時(shí)候喊递,定義了4個(gè)標(biāo)準(zhǔn)的meta-annotation類型,它們用來提供對(duì)其他注解的類型作說明俏讹。
1.@Target
2.@Retention
3.@Documented
4.@Inherited
18、Java中String的了解?
在源碼中string是用final 進(jìn)行修飾殉疼,它是不可更改,不可繼承的常量恋腕。
19伙单、String為什么要設(shè)計(jì)成不可變的?
1布疼、字符串池的需求
字符串池是方法區(qū)(Method Area)中的一塊特殊的存儲(chǔ)區(qū)域漩绵。當(dāng)一個(gè)字符串已經(jīng)被創(chuàng)建并且該字符串在 池 中宝踪,該字符串的引用會(huì)立即返回給變量,而不是重新創(chuàng)建一個(gè)字符串再將引用返回給變量颤芬。如果字符串不是不可變的,那么改變一個(gè)引用(如: string2)的字符串將會(huì)導(dǎo)致另一個(gè)引用(如: string1)出現(xiàn)臟數(shù)據(jù)菱魔。
2篡殷、允許字符串緩存哈希碼
在java中常常會(huì)用到字符串的哈希碼桩卵,例如: HashMap 胜嗓。String的不變性保證哈希碼始終一寥粹,因此牵啦,他可以不用擔(dān)心變化的出現(xiàn)。 這種方法意味著不必每次使用時(shí)都重新計(jì)算一次哈希碼——這樣妄痪,效率會(huì)高很多。
3楞件、安全
String廣泛的用于java 類中的參數(shù)衫生,如:網(wǎng)絡(luò)連接(Network connetion),打開文件(opening files )等等土浸。如果String不是不可變的,網(wǎng)絡(luò)連接斯撮、文件將會(huì)被改變——這將會(huì)導(dǎo)致一系列的安全威脅。操作的方法本以為連接上了一臺(tái)機(jī)器,但實(shí)際上卻不是螃征。由于反射中的參數(shù)都是字符串撵术,同樣处坪,也會(huì)引起一系列的安全問題。
20骂铁、Object類的equal和hashCode方法重寫,為什么欢唾?
首先equals與hashcode間的關(guān)系是這樣的:
1浅碾、如果兩個(gè)對(duì)象相同(即用equals比較返回true),那么它們的hashCode值一定要相同怖糊;
2姐直、如果兩個(gè)對(duì)象的hashCode相同辫狼,它們并不一定相同(即用equals比較返回false)? ?
由于為了提高程序的效率才實(shí)現(xiàn)了hashcode方法置济,先進(jìn)行hashcode的比較羞酗,如果不同,那沒就不必在進(jìn)行equals的比較了剃盾,這樣就大大減少了equals比較的次數(shù)尽爆,這對(duì)比需要比較的數(shù)量很大的效率提高是很明顯的
21厕氨、List,Set,Map的區(qū)別?
Set是最簡單的一種集合胃惜。集合中的對(duì)象不按特定的方式排序,并且沒有重復(fù)對(duì)象哪雕。 Set接口主要實(shí)現(xiàn)了兩個(gè)實(shí)現(xiàn)類:HashSet: HashSet類按照哈希算法來存取集合中的對(duì)象船殉,存取速度比較快?
TreeSet :TreeSet類實(shí)現(xiàn)了SortedSet接口,能夠?qū)现械膶?duì)象進(jìn)行排序斯嚎。
List的特征是其元素以線性方式存儲(chǔ)利虫,集合中可以存放重復(fù)對(duì)象挨厚。?
ArrayList() : 代表長度可以改變得數(shù)組】繁梗可以對(duì)元素進(jìn)行隨機(jī)的訪問疫剃,向ArrayList()中插入與刪除元素的速度慢。?
LinkedList(): 在實(shí)現(xiàn)中采用鏈表數(shù)據(jù)結(jié)構(gòu)硼讽。插入和刪除速度快巢价,訪問速度慢。
Map 是一種把鍵對(duì)象和值對(duì)象映射的集合固阁,它的每一個(gè)元素都包含一對(duì)鍵對(duì)象和值對(duì)象壤躲。 Map沒有繼承于Collection接口 從Map集合中檢索元素時(shí),只要給出鍵對(duì)象备燃,就會(huì)返回對(duì)應(yīng)的值對(duì)象碉克。
HashMap:Map基于散列表的實(shí)現(xiàn)。插入和查詢“鍵值對(duì)”的開銷是固定的赚爵∶拚停可以通過構(gòu)造器設(shè)置容量capacity和負(fù)載因子load factor,以調(diào)整容器的性能冀膝。
LinkedHashMap: 類似于HashMap唁奢,但是迭代遍歷它時(shí),取得“鍵值對(duì)”的順序是其插入次序窝剖,或者是最近最少使用(LRU)的次序麻掸。只比HashMap慢一點(diǎn)。而在迭代訪問時(shí)發(fā)而更快赐纱,因?yàn)樗褂面湵砭S護(hù)內(nèi)部次序脊奋。
TreeMap : 基于紅黑樹數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)。查看“鍵”或“鍵值對(duì)”時(shí)疙描,它們會(huì)被排序(次序由Comparabel或Comparator決定)诚隙。TreeMap的特點(diǎn)在 于,你得到的結(jié)果是經(jīng)過排序的起胰。TreeMap是唯一的帶有subMap()方法的Map久又,它可以返回一個(gè)子樹。
WeakHashMao :弱鍵(weak key)Map效五,Map中使用的對(duì)象也被允許釋放: 這是為解決特殊問題設(shè)計(jì)的地消。如果沒有map之外的引用指向某個(gè)“鍵”,則此“鍵”可以被垃圾收集器回收畏妖。?
26脉执、ArrayMap和HashMap的對(duì)比?
1、存儲(chǔ)方式不同
HashMap內(nèi)部有一個(gè)HashMapEntry[]對(duì)象戒劫,每一個(gè)鍵值對(duì)都存儲(chǔ)在這個(gè)對(duì)象里半夷,當(dāng)使用put方法添加鍵值對(duì)時(shí)婆廊,就會(huì)new一個(gè)HashMapEntry對(duì)象,
2玻熙、添加數(shù)據(jù)時(shí)擴(kuò)容時(shí)的處理不一樣否彩,進(jìn)行了new操作,重新創(chuàng)建對(duì)象嗦随,開銷很大列荔。ArrayMap用的是copy數(shù)據(jù),所以效率相對(duì)要高枚尼。
3贴浙、ArrayMap提供了數(shù)組收縮的功能,在clear或remove后署恍,會(huì)重新收縮數(shù)組崎溃,是否空間
4、ArrayMap采用二分法查找盯质;
29袁串、HashMap和HashTable的區(qū)別?
1 HashMap不是線程安全的,效率高一點(diǎn)呼巷、方法不是Synchronize的要提供外同步囱修,有containsvalue和containsKey方法。
hashtable是王悍,線程安全破镰,不允許有null的鍵和值,效率稍低压储,方法是是Synchronize的鲜漩。有contains方法方法。Hashtable 繼承于Dictionary 類
30集惋、HashMap與HashSet的區(qū)別?
hashMap:HashMap實(shí)現(xiàn)了Map接口,HashMap儲(chǔ)存鍵值對(duì),使用put()方法將元素放入map中,HashMap中使用鍵對(duì)象來計(jì)算hashcode值,HashMap比較快孕似,因?yàn)槭鞘褂梦ㄒ坏逆I來獲取對(duì)象。
HashSet實(shí)現(xiàn)了Set接口刮刑,HashSet僅僅存儲(chǔ)對(duì)象鳞青,使用add()方法將元素放入set中,HashSet使用成員對(duì)象來計(jì)算hashcode值为朋,對(duì)于兩個(gè)對(duì)象來說hashcode可能相同,所以equals()方法用來判斷對(duì)象的相等性厚脉,如果兩個(gè)對(duì)象不同的話习寸,那么返回false。HashSet較HashMap來說比較慢傻工。
31霞溪、HashSet與HashMap怎么判斷集合元素重復(fù)孵滞?
HashSet不能添加重復(fù)的元素,當(dāng)調(diào)用add(Object)方法時(shí)候鸯匹,
首先會(huì)調(diào)用Object的hashCode方法判hashCode是否已經(jīng)存在坊饶,如不存在則直接插入元素;如果已存在則調(diào)用Object對(duì)象的equals方法判斷是否返回true殴蓬,如果為true則說明元素已經(jīng)存在匿级,如為false則插入元素。
33染厅、ArrayList和LinkedList的區(qū)別痘绎,以及應(yīng)用場景?
ArrayList是基于數(shù)組實(shí)現(xiàn)的,ArrayList線程不安全肖粮。
LinkedList是基于雙鏈表實(shí)現(xiàn)的:
使用場景:
(1)如果應(yīng)用程序?qū)Ω鱾€(gè)索引位置的元素進(jìn)行大量的存取或刪除操作孤页,ArrayList對(duì)象要遠(yuǎn)優(yōu)于LinkedList對(duì)象;
( 2 ) 如果應(yīng)用程序主要是對(duì)列表進(jìn)行循環(huán)涩馆,并且循環(huán)時(shí)候進(jìn)行插入或者刪除操作行施,LinkedList對(duì)象要遠(yuǎn)優(yōu)于ArrayList對(duì)象;
34魂那、數(shù)組和鏈表的區(qū)別
數(shù)組:是將元素在內(nèi)存中連續(xù)存儲(chǔ)的蛾号;它的優(yōu)點(diǎn):因?yàn)閿?shù)據(jù)是連續(xù)存儲(chǔ)的,內(nèi)存地址連續(xù)冰寻,所以在查找數(shù)據(jù)的時(shí)候效率比較高须教;它的缺點(diǎn):在存儲(chǔ)之前,我們需要申請一塊連續(xù)的內(nèi)存空間斩芭,并且在編譯的時(shí)候就必須確定好它的空間的大小轻腺。在運(yùn)行的時(shí)候空間的大小是無法隨著你的需要進(jìn)行增加和減少而改變的,當(dāng)數(shù)據(jù)兩比較大的時(shí)候划乖,有可能會(huì)出現(xiàn)越界的情況贬养,數(shù)據(jù)比較小的時(shí)候,又有可能會(huì)浪費(fèi)掉內(nèi)存空間琴庵。在改變數(shù)據(jù)個(gè)數(shù)時(shí)误算,增加、插入迷殿、刪除數(shù)據(jù)效率比較低儿礼。
鏈表:是動(dòng)態(tài)申請內(nèi)存空間,不需要像數(shù)組需要提前申請好內(nèi)存的大小庆寺,鏈表只需在用的時(shí)候申請就可以蚊夫,根據(jù)需要來動(dòng)態(tài)申請或者刪除內(nèi)存空間,對(duì)于數(shù)據(jù)增加和刪除以及插入比數(shù)組靈活懦尝。還有就是鏈表中數(shù)據(jù)在內(nèi)存中可以在任意的位置知纷,通過應(yīng)用來關(guān)聯(lián)數(shù)據(jù)(就是通過存在元素的指針來聯(lián)系)
35壤圃、開啟線程的三種方式?
ava有三種創(chuàng)建線程的方式琅轧,分別是繼承Thread類伍绳、實(shí)現(xiàn)Runable接口和使用線程池?
36、線程和進(jìn)程的區(qū)別乍桂?
線程是進(jìn)程的子集冲杀,一個(gè)進(jìn)程可以有很多線程,每條線程并行執(zhí)行不同的任務(wù)模蜡。不同的進(jìn)程使用不同的內(nèi)存空間漠趁,而所有的線程共享一片相同的內(nèi)存空間。別把它和棧內(nèi)存搞混忍疾,每個(gè)線程都擁有單獨(dú)的棧內(nèi)存用來存儲(chǔ)本地?cái)?shù)據(jù)闯传。
38、run()和start()方法區(qū)別?
這個(gè)問題經(jīng)常被問到卤妒,但還是能從此區(qū)分出面試者對(duì)Java線程模型的理解程度甥绿。start()方法被用來啟動(dòng)新創(chuàng)建的線程,而且start()內(nèi)部調(diào)用了run()方法则披,這和直接調(diào)用run()方法的效果不一樣共缕。當(dāng)你調(diào)用run()方法的時(shí)候,只會(huì)是在原來的線程中調(diào)用士复,沒有新的線程啟動(dòng)图谷,start()方法才會(huì)啟動(dòng)新線程。
39阱洪、如何控制某個(gè)方法允許并發(fā)訪問線程的個(gè)數(shù)便贵?
semaphore.acquire() 請求一個(gè)信號(hào)量,這時(shí)候的信號(hào)量個(gè)數(shù)-1(一旦沒有可使用的信號(hào)量冗荸,也即信號(hào)量個(gè)數(shù)變?yōu)樨?fù)數(shù)時(shí)承璃,再次請求的時(shí)候就會(huì)阻塞,直到其他線程釋放了信號(hào)量)
semaphore.release() 釋放一個(gè)信號(hào)量蚌本,此時(shí)信號(hào)量個(gè)數(shù)+1
40盔粹、在Java中wait和seelp方法的不同;
Java程序中wait 和 sleep都會(huì)造成某種形式的暫停程癌,它們可以滿足不同的需要舷嗡。wait()方法用于線程間通信,如果等待條件為真且其它線程被喚醒時(shí)它會(huì)釋放鎖嵌莉,而sleep()方法僅僅釋放CPU資源或者讓當(dāng)前線程停止執(zhí)行一段時(shí)間咬崔,但不會(huì)釋放鎖。
41、談?wù)?/b>wait/notify關(guān)鍵字的理解?
等待對(duì)象的同步鎖,需要獲得該對(duì)象的同步鎖才可以調(diào)用這個(gè)方法,否則編譯可以通過垮斯,但運(yùn)行時(shí)會(huì)收到一個(gè)異常:IllegalMonitorStateException。
調(diào)用任意對(duì)象的 wait() 方法導(dǎo)致該線程阻塞只祠,該線程不可繼續(xù)執(zhí)行兜蠕,并且該對(duì)象上的鎖被釋放。
喚醒在等待該對(duì)象同步鎖的線程(只喚醒一個(gè),如果有多個(gè)在等待),注意的是在調(diào)用此方法的時(shí)候抛寝,并不能確切的喚醒某一個(gè)等待狀態(tài)的線程熊杨,而是由JVM確定喚醒哪個(gè)線程,而且不是按優(yōu)先級(jí)盗舰。
調(diào)用任意對(duì)象的notify()方法則導(dǎo)致因調(diào)用該對(duì)象的 wait()方法而阻塞的線程中隨機(jī)選擇的一個(gè)解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)晶府。
42、什么導(dǎo)致線程阻塞钻趋?線程如何關(guān)閉川陆?
阻塞式方法是指程序會(huì)一直等待該方法完成期間不做其他事情,ServerSocket的accept()方法就是一直等待客戶端連接蛮位。這里的阻塞是指調(diào)用結(jié)果返回之前较沪,當(dāng)前線程會(huì)被掛起,直到得到結(jié)果之后才會(huì)返回失仁。此外尸曼,還有異步和非阻塞式方法在任務(wù)完成前就返回。
一種是調(diào)用它里面的stop()方法
另一種就是你自己設(shè)置一個(gè)停止線程的標(biāo)記 (推薦這種)
43萄焦、如何保證線程安全控轿?
1.synchronized;
2.Object方法中的wait,notify拂封;
3.ThreadLocal機(jī)制 ? 來實(shí)現(xiàn)的茬射。
44、如何實(shí)現(xiàn)線程同步烘苹?
1躲株、synchronized關(guān)鍵字修改的方法。2镣衡、synchronized關(guān)鍵字修飾的語句塊3霜定、使用特殊域變量(volatile)實(shí)現(xiàn)線程同步
45、線程間操作List?
List list = Collections.synchronizedList(new ArrayList());
46廊鸥、談?wù)剬?duì)Synchronized關(guān)鍵字望浩,類鎖,方法鎖惰说,重入鎖的理解?
java的對(duì)象鎖和類鎖:java的對(duì)象鎖和類鎖在鎖的概念上基本上和內(nèi)置鎖是一致的磨德,但是,兩個(gè)鎖實(shí)際是有很大的區(qū)別的,對(duì)象鎖是用于對(duì)象實(shí)例方法典挑,或者一個(gè)對(duì)象實(shí)例上的酥宴,類鎖是用于類的靜態(tài)方法或者一個(gè)類的class對(duì)象上的。我們知道您觉,類的對(duì)象實(shí)例可以有很多個(gè)拙寡,但是每個(gè)類只有一個(gè)class對(duì)象,所以不同對(duì)象實(shí)例的對(duì)象鎖是互不干擾的琳水,但是每個(gè)類只有一個(gè)類鎖肆糕。但是有一點(diǎn)必須注意的是,其實(shí)類鎖只是一個(gè)概念上的東西在孝,并不是真實(shí)存在的诚啃,它只是用來幫助我們理解鎖定實(shí)例方法和靜態(tài)方法的區(qū)別的
49、synchronized?和volatile?關(guān)鍵字的區(qū)別?
1.volatile本質(zhì)是在告訴jvm當(dāng)前變量在寄存器(工作內(nèi)存)中的值是不確定的私沮,需要從主存中讀仁际辍;synchronized則是鎖定當(dāng)前變量顾彰,只有當(dāng)前線程可以訪問該變量极阅,其他線程被阻塞住。
2.volatile僅能使用在變量級(jí)別涨享;synchronized則可以使用在變量筋搏、方法、和類級(jí)別的
3.volatile僅能實(shí)現(xiàn)變量的修改可見性厕隧,不能保證原子性奔脐;而synchronized則可以保證變量的修改可見性和原子性
4.volatile不會(huì)造成線程的阻塞;synchronized可能會(huì)造成線程的阻塞吁讨。
5.volatile標(biāo)記的變量不會(huì)被編譯器優(yōu)化髓迎;synchronized標(biāo)記的變量可以被編譯器優(yōu)化
51、ReentrantLock?建丧、synchronized和volatile比較?
ava在過去很長一段時(shí)間只能通過synchronized關(guān)鍵字來實(shí)現(xiàn)互斥排龄,它有一些缺點(diǎn)。比如你不能擴(kuò)展鎖之外的方法或者塊邊界翎朱,嘗試獲取鎖時(shí)不能中途取消等橄维。Java 5 通過Lock接口提供了更復(fù)雜的控制來解決這些問題。 ReentrantLock 類實(shí)現(xiàn)了 Lock拴曲,它擁有與 synchronized 相同的并發(fā)性和內(nèi)存語義且它還具有可擴(kuò)展性争舞。
53、死鎖的四個(gè)必要條件澈灼?
死鎖產(chǎn)生的原因
1. 系統(tǒng)資源的競爭
系統(tǒng)資源的競爭導(dǎo)致系統(tǒng)資源不足竞川,以及資源分配不當(dāng)店溢,導(dǎo)致死鎖。
2. 進(jìn)程運(yùn)行推進(jìn)順序不合適
互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用委乌,即在一段時(shí)間內(nèi)某 資源僅為一個(gè)進(jìn)程所占有床牧。此時(shí)若有其他進(jìn)程請求該資源,則請求進(jìn)程只能等待遭贸。
請求與保持條件:進(jìn)程已經(jīng)保持了至少一個(gè)資源叠赦,但又提出了新的資源請求,而該資源 已被其他進(jìn)程占有革砸,此時(shí)請求進(jìn)程被阻塞,但對(duì)自己已獲得的資源保持不放糯累。
不可剝奪條件:進(jìn)程所獲得的資源在未使用完畢之前算利,不能被其他進(jìn)程強(qiáng)行奪走,即只能 由獲得該資源的進(jìn)程自己來釋放(只能是主動(dòng)釋放)泳姐。
循環(huán)等待條件: 若干進(jìn)程間形成首尾相接循環(huán)等待資源的關(guān)系
這四個(gè)條件是死鎖的必要條件效拭,只要系統(tǒng)發(fā)生死鎖,這些條件必然成立胖秒,而只要上述條件之一不滿足缎患,就不會(huì)發(fā)生死鎖。
死鎖的避免與預(yù)防:
死鎖避免的基本思想:
系統(tǒng)對(duì)進(jìn)程發(fā)出每一個(gè)系統(tǒng)能夠滿足的資源申請進(jìn)行動(dòng)態(tài)檢查,并根據(jù)檢查結(jié)果決定是否分配資源,如果分配后系統(tǒng)可能發(fā)生死鎖,則不予分配,否則予以分配阎肝。這是一種保證系統(tǒng)不進(jìn)入死鎖狀態(tài)的動(dòng)態(tài)策略挤渔。
理解了死鎖的原因,尤其是產(chǎn)生死鎖的四個(gè)必要條件风题,就可以最大可能地避免判导、預(yù)防和解除死鎖。所以沛硅,在系統(tǒng)設(shè)計(jì)眼刃、進(jìn)程調(diào)度等方面注意如何讓這四個(gè)必要條件不成立,如何確定資源的合理分配算法摇肌,避免進(jìn)程永久占據(jù)系統(tǒng)資源擂红。此外,也要防止進(jìn)程在處于等待狀態(tài)的情況下占用資源围小。因此昵骤,對(duì)資源的分配要給予合理的規(guī)劃。
死鎖避免和死鎖預(yù)防的區(qū)別:
死鎖預(yù)防是設(shè)法至少破壞產(chǎn)生死鎖的四個(gè)必要條件之一,嚴(yán)格的防止死鎖的出現(xiàn),而死鎖避免則不那么嚴(yán)格的限制產(chǎn)生死鎖的必要條件的存在,因?yàn)榧词顾梨i的必要條件存在,也不一定發(fā)生死鎖吩抓。死鎖避免是在系統(tǒng)運(yùn)行過程中注意避免死鎖的最終發(fā)生涉茧。
56、什么是線程池疹娶,如何使用?
創(chuàng)建線程要花費(fèi)昂貴的資源和時(shí)間伴栓,如果任務(wù)來了才創(chuàng)建線程那么響應(yīng)時(shí)間會(huì)變長,而且一個(gè)進(jìn)程能創(chuàng)建的線程數(shù)有限。為了避免這些問題钳垮,在程序啟動(dòng)的時(shí)候就創(chuàng)建若干線程來響應(yīng)處理惑淳,它們被稱為線程池,里面的線程叫工作線程饺窿。從JDK1.5開始歧焦,Java API提供了Executor框架讓你可以創(chuàng)建不同的線程池。比如單線程池肚医,每次處理一個(gè)任務(wù)绢馍;數(shù)目固定的線程池或者是緩存線程池(一個(gè)適合很多生存期短的任務(wù)的程序的可擴(kuò)展線程池)。
57肠套、Java中堆和棧有什么不同舰涌?
為什么把這個(gè)問題歸類在多線程和并發(fā)面試題里?因?yàn)闂J且粔K和線程緊密相關(guān)的內(nèi)存區(qū)域你稚。每個(gè)線程都有自己的棧內(nèi)存瓷耙,用于存儲(chǔ)本地變量,方法參數(shù)和棧調(diào)用刁赖,一個(gè)線程中存儲(chǔ)的變量對(duì)其它線程是不可見的搁痛。而堆是所有線程共享的一片公用內(nèi)存區(qū)域。對(duì)象都在堆里創(chuàng)建宇弛,為了提升效率線程會(huì)從堆中弄一個(gè)緩存到自己的棧鸡典,如果多個(gè)線程使用該變量就可能引發(fā)問題,這時(shí)volatile 變量就可以發(fā)揮作用了涯肩,它要求線程從主存中讀取變量的值轿钠。
58、有三個(gè)線程T1病苗,T2疗垛,T3,怎么確保它們按順序執(zhí)行硫朦?
在多線程中有多種方法讓線程按特定順序執(zhí)行贷腕,你可以用線程類的join()方法在一個(gè)線程中啟動(dòng)另一個(gè)線程,另外一個(gè)線程完成該線程繼續(xù)執(zhí)行咬展。為了確保三個(gè)線程的順序你應(yīng)該先啟動(dòng)最后一個(gè)(T3調(diào)用T2泽裳,T2調(diào)用T1),這樣T1就會(huì)先完成而T3最后完成破婆。
線程間通信
?我們知道線程是CPU調(diào)度的最小單位涮总。在Android中主線程是不能夠做耗時(shí)操作的,子線程是不能夠更新UI的祷舀。而線程間通信的方式有很多瀑梗,比如廣播烹笔,Eventbus,接口回掉抛丽,在Android中主要是使用handler谤职。handler通過調(diào)用sendmessage方法,將保存消息的Message發(fā)送到Messagequeue中亿鲜,而looper對(duì)象不斷的調(diào)用loop方法允蜈,從messageueue中取出message,交給handler處理蒿柳,從而完成線程間通信饶套。
線程池
?Android中常見的線程池有四種,F(xiàn)ixedThreadPool垒探、CachedThreadPool凤跑、ScheduledThreadPool、SingleThreadExecutor叛复。
?FixedThreadPool線程池是通過Executors的new FixedThreadPool方法來創(chuàng)建。它的特點(diǎn)是該線程池中的線程數(shù)量是固定的扔仓。即使線程處于閑置的狀態(tài)褐奥,它們也不會(huì)被回收,除非線程池被關(guān)閉翘簇。當(dāng)所有的線程都處于活躍狀態(tài)的時(shí)候撬码,新任務(wù)就處于隊(duì)列中等待線程來處理。注意版保,F(xiàn)ixedThreadPool只有核心線程呜笑,沒有非核心線程。
CachedThreadPool線程池是通過Executors的newCachedThreadPool進(jìn)行創(chuàng)建的彻犁。它是一種線程數(shù)目不固定的線程池叫胁,它沒有核心線程,只有非核心線程汞幢,當(dāng)線程池中的線程都處于活躍狀態(tài)驼鹅,就會(huì)創(chuàng)建新的線程來處理新的任務(wù)。否則就會(huì)利用閑置的線程來處理新的任務(wù)森篷。線程池中的線程都有超時(shí)機(jī)制输钩,這個(gè)超時(shí)機(jī)制時(shí)長是60s,超過這個(gè)時(shí)間仲智,閑置的線程就會(huì)被回收买乃。這種線程池適合處理大量并且耗時(shí)較少的任務(wù)。這里得說一下钓辆,CachedThreadPool的任務(wù)隊(duì)列剪验,基本都是空的肴焊。
ScheduledThreadPool線程池是通過Executors的newScheduledThreadPool進(jìn)行創(chuàng)建的,它的核心線程是固定的碉咆,但是非核心線程數(shù)是不固定的抖韩,并且當(dāng)非核心線程一處于空閑狀態(tài),就立即被回收疫铜。這種線程適合執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)茂浮。
SingleThreadExecutor線程池是通過Executors的newSingleThreadExecutor方法來創(chuàng)建的,這類線程池中只有一個(gè)核心線程壳咕,也沒有非核心線程席揽,這就確保了所有任務(wù)能夠在同一個(gè)線程并且按照順序來執(zhí)行,這樣就不需要考慮線程同步的問題谓厘。
AsyncTask的工作原理
AsyncTask是Android本身提供的一種輕量級(jí)的異步任務(wù)類幌羞。它可以在線程池中執(zhí)行后臺(tái)任務(wù),然后把執(zhí)行的進(jìn)度和最終的結(jié)果傳遞給主線程更新UI竟稳。實(shí)際上属桦,AsyncTask內(nèi)部是封裝了Thread和Handler。雖然AsyncTask很方便的執(zhí)行后臺(tái)任務(wù)他爸,以及在主線程上更新UI聂宾,但是,AsyncTask并不合適進(jìn)行特別耗時(shí)的后臺(tái)操作诊笤,對(duì)于特別耗時(shí)的任務(wù)系谐,個(gè)人還是建議使用線程池。
AsyncTask提供有4個(gè)核心方法:
1讨跟、onPreExecute():該方法在主線程中執(zhí)行纪他,在執(zhí)行異步任務(wù)之前會(huì)被調(diào)用,一般用于一些準(zhǔn)備工作晾匠。
2茶袒、doInBackground(String... params):這個(gè)方法是在線程池中執(zhí)行,此方法用于執(zhí)行異步任務(wù)凉馆。在這個(gè)方法中可以通過publishProgress方法來更新任務(wù)的進(jìn)度弹谁,publishProgress方法會(huì)調(diào)用onProgressUpdate方法,另外句喜,任務(wù)的結(jié)果返回給onPostExecute方法预愤。
3、onProgressUpdate(Object... values):該方法在主線程中執(zhí)行咳胃,主要用于任務(wù)進(jìn)度更新的時(shí)候植康,該方法會(huì)被調(diào)用。
4展懈、onPostExecute(Long aLong):在主線程中執(zhí)行销睁,在異步任務(wù)執(zhí)行完畢之后供璧,該方法會(huì)被調(diào)用,該方法的參數(shù)及為后臺(tái)的返回結(jié)果冻记。
除了這幾個(gè)方法之外還有一些不太常用的方法睡毒,如onCancelled(),在異步任務(wù)取消的情況下,該方法會(huì)被調(diào)用冗栗。
源碼可以知道從上面的execute方法內(nèi)部調(diào)用的是executeOnExecutor()方法演顾,即executeOnExecutor(sDefaultExecutor, params);而sDefaultExecutor實(shí)際上是一個(gè)串行的線程池。而onPreExecute()方法在這里就會(huì)被調(diào)用了隅居。接著看這個(gè)線程池钠至。AsyncTask的執(zhí)行是排隊(duì)執(zhí)行的,因?yàn)橛嘘P(guān)鍵字synchronized胎源,而AsyncTask的Params參數(shù)就封裝成為FutureTask類棉钧,F(xiàn)utureTask這個(gè)類是一個(gè)并發(fā)類,在這里它充當(dāng)了Runnable的作用涕蚤。接著FutureTask會(huì)交給SerialExecutor的execute方法去處理宪卿,而SerialExecutor的executor方法首先就會(huì)將FutureTask添加到mTasks隊(duì)列中,如果這個(gè)時(shí)候沒有任務(wù)万栅,就會(huì)調(diào)用scheduleNext()方法愧捕,執(zhí)行下一個(gè)任務(wù)。如果有任務(wù)的話申钩,則執(zhí)行完畢后最后在調(diào)用 scheduleNext();執(zhí)行下一個(gè)任務(wù)。直到所有任務(wù)被執(zhí)行完畢瘪阁。而AsyncTask的構(gòu)造方法中有一個(gè)call()方法撒遣,而這個(gè)方法由于會(huì)被FutureTask的run方法執(zhí)行。所以最終這個(gè)call方法會(huì)在線程池中執(zhí)行管跺。而doInBackground這個(gè)方法就是在這里被調(diào)用的义黎。我們好好研究一下這個(gè)call()方法。mTaskInvoked.set(true);表示當(dāng)前任務(wù)已經(jīng)執(zhí)行過了豁跑。接著執(zhí)行doInBackground方法廉涕,最后將結(jié)果通過postResult(result);方法進(jìn)行傳遞。postResult()方法中通過sHandler來發(fā)送消息艇拍,sHandler的中通過消息的類型來判斷一個(gè)MESSAGE_POST_RESULT狐蜕,這種情況就是調(diào)用onPostExecute(result)方法或者是onCancelled(result)。另一種消息類型是MESSAGE_POST_PROGRESS則調(diào)用更新進(jìn)度onProgressUpdate卸夕。
Binder的工作機(jī)制
?直觀來說层释,Binder是Android中的一個(gè)類,它實(shí)現(xiàn)了IBinder接口快集,從IPC的角度來說贡羔,Binder是Android中的一種跨進(jìn)程通信的一種方式廉白,同時(shí)還可以理解為是一種虛擬的物理設(shè)備,它的設(shè)備驅(qū)動(dòng)是/dev/binder/乖寒。從Framework角度來說再愈,Binder是ServiceManager的橋梁忍抽。從應(yīng)用層來說,Binder是客戶端和服務(wù)端進(jìn)行通信的媒介。
我們先來了解一下這個(gè)類中每個(gè)方法的含義:
DESCRIPTOR:Binder的唯一標(biāo)識(shí)赏壹,一般用于當(dāng)前Binder的類名表示。
asInterface(android.os.IBinder obj):用于將服務(wù)端的Binder對(duì)象轉(zhuǎn)換成客戶端所需的AIDL接口類型的對(duì)象崩泡,這種轉(zhuǎn)化過程是區(qū)分進(jìn)程的窟坐,如果客戶端和服務(wù)端位于同一個(gè)進(jìn)程,那么這個(gè)方法返回的是服務(wù)端的stub對(duì)象本身痊班,否則返回的是系統(tǒng)封裝后的Stub.proxy對(duì)象勤婚。
asBinder():用于返回當(dāng)前Binder對(duì)象。
onTransact:該方法運(yùn)行在服務(wù)端的Binder線程池中涤伐,當(dāng)客戶端發(fā)起跨進(jìn)程通信請求的時(shí)候馒胆,遠(yuǎn)程請求通過系統(tǒng)底層封裝后交給該方法處理。注意這個(gè)方法public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)凝果,服務(wù)端通過code可以確定客戶端所請求的目標(biāo)方法是什么祝迂,接著從data中取出目標(biāo)方法所需的參數(shù),然后執(zhí)行目標(biāo)方法器净。當(dāng)目標(biāo)方法執(zhí)行完畢后型雳,就像reply中寫入返回值。這個(gè)方法的執(zhí)行過程就是這樣的山害。如果這個(gè)方法返回false,客戶端是會(huì)請求失敗的冤荆,所以我們可以在這個(gè)方法中做一些安全驗(yàn)證权纤。?
Binder的工作機(jī)制但是要注意一些問題:1钓简、當(dāng)客戶端發(fā)起請求時(shí)汹想,由于當(dāng)前線程會(huì)被掛起,直到服務(wù)端返回?cái)?shù)據(jù)古掏,如果這個(gè)遠(yuǎn)程方法很耗時(shí)的話坐榆,那么是不能夠在UI線程冗茸,也就是主線程中發(fā)起這個(gè)遠(yuǎn)程請求的匹中。
2顶捷、由于Service的Binder方法運(yùn)行在線程池中屎篱,所以Binder方法不管是耗時(shí)還是不耗時(shí)都應(yīng)該采用同步的方式,因?yàn)樗呀?jīng)運(yùn)行在一個(gè)線程中了重虑。
view的事件分發(fā)和view的工作原理
Android自定義view秦士,我們都知道實(shí)現(xiàn)有三部曲隧土,onMeasure(),onLayout(),onDraw()。View的繪制流程是從viewRoot的perfromTraversal方法開始的辐脖。它經(jīng)過measure嗜价,layout幕庐,draw方法才能夠?qū)iew繪制出來翔脱。其中measure是測量寬高的媒鼓,layout是確定view在父容器上的擺布位置的绿鸣,draw是將view繪制到屏幕上的疚沐。
Measure:
view的測量是需要MeasureSpc(測量規(guī)格),它代表一個(gè)32位int值亮蛔,高2位代表SpecMode(測量模式)究流,低(30)位的代表SpecSize(某種測量模式下的規(guī)格大小)。而一組SpecMode和SpeSize可以打包為一個(gè)MeasureSpec,反之神得,MeasureSpec可以解包得到SpecMode和SpeSize的值哩簿。SpecMode有三類:
unSpecified:父容器不對(duì)view有任何限制酝静,要多大有多大别智。一般系統(tǒng)用這個(gè)多亿遂。
Exactly:父容器已經(jīng)檢測出view所需要的精確大小,這個(gè)時(shí)候挪钓,view的大小就是SpecSize所指定的值碌上,它對(duì)應(yīng)者layout布局中的math_parent或者是具體的數(shù)值
At_most:父容器指定了一個(gè)可用大小的SpecSize,view的大小不能夠大于這個(gè)值浦徊,它對(duì)應(yīng)這布局中的wrao_content.
對(duì)于普通的view盔性,它的MeasureSpec是由父容器的MeasureSpec和自身的layoutParam共同決定的冕香,一旦MeasureSpec確定后悉尾,onMeasure就可以確定view的寬高了。
View的measure過程:
onMeasure方法中有個(gè)setMeasureDimenSion方法來設(shè)置view的寬高測量值愕难,而setMeasureDimenSion有個(gè)getDefaultSize()方法作為參數(shù)猫缭。一般情況下,我們只需要關(guān)注at_most和exactly兩種情況翘悉,getDefaultSize的返回值就是measureSpec中的SpecSize,而這個(gè)值基本就是view測量后的大小妖混。而UnSpecified這種情況制市,一般是系統(tǒng)內(nèi)部的測量過程弊予,它是需要考慮view的背景這些因素的汉柒。
前面說的是view的測量過程碾褂,而viewGroup的measure過程:
對(duì)于viewGroup來說,除了完成自己的measure過程以外嘀略,還要遍歷去調(diào)用子類的measure方法帜羊,各個(gè)子元素在遞歸執(zhí)行這個(gè)過程讼育,viewGroup是一個(gè)抽象的類稠集,沒有提供有onMeasure方法巍杈,但是提供了一個(gè)measureChildren的方法筷畦。measureChild方法的思想就是取出子元素的layoutParams,然后通過getChildMeasureSpec來常見子元素的MeasureSpec,然后子元素在電泳measure方法進(jìn)行測量鳖宾。由于viewGroup子類有不同的布局方式,導(dǎo)致他們的測量細(xì)節(jié)不一樣渔肩,所以viewGroup不能象view一樣調(diào)用onMeasure方法進(jìn)行測量周偎。
注意:在activity的生命周期中是沒有辦法正確的獲取view的寬高的蓉坎,原因就是view沒有測量完胡嘿。
在onWindowFocuschanged方法中獲取 ----改方法含義是view已經(jīng)初始化完畢
View.post()方法衷敌,將潤那邊了投遞到消息隊(duì)列的尾部缴罗。
使用viewTreeObserver的回調(diào)來完成。
通過view.measure方式手動(dòng)測量弓柱。
onLayout
普通的view的話矢空,可以通過setFrame方法來的到view四個(gè)頂點(diǎn)的位置屁药,也就確定了view在父容器的位置酿箭,接著就調(diào)用onLayout方法趾娃,該方法是父容器確定子元素的位置抬闷。
onDraw
該方法就是將view繪制到屏幕上。分以下幾步
繪制背景眷茁,
繪制自己纵诞,
繪制child浙芙,
繪制裝飾嗡呼。
Android中性能優(yōu)化
由于手機(jī)硬件的限制晤锥,內(nèi)存和CPU都無法像pc一樣具有超大的內(nèi)存,Android手機(jī)上女轿,過多的使用內(nèi)存蛉迹,會(huì)容易導(dǎo)致oom北救,過多的使用CPU資源珍策,會(huì)導(dǎo)致手機(jī)卡頓宅倒,甚至導(dǎo)致anr拐迁。我主要是從一下幾部分進(jìn)行優(yōu)化:
布局優(yōu)化线召,繪制優(yōu)化缓淹,內(nèi)存泄漏優(yōu)化,響應(yīng)速度優(yōu)化前酿,listview優(yōu)化罢维,bitmap優(yōu)化肺孵,線程優(yōu)化
布局優(yōu)化:工具 hierarchyviewer平窘,解決方式:
1瑰艘、刪除無用的空間和層級(jí)肤舞。
2李剖、選擇性能較低的viewgroup篙顺,如Relativelayout德玫,如果可以選擇Relativelayout也可以使用LinearLayout,就優(yōu)先使用LinearLayout宰僧,因?yàn)橄鄬?duì)來說Relativelayout功能較為復(fù)雜撒桨,會(huì)占用更多的CPU資源凤类。
3、使用標(biāo)簽重用布局佃延,減少層級(jí)履肃,進(jìn)行預(yù)加載尺棋,使用的時(shí)候才加載膘螟。
繪制優(yōu)化
繪制優(yōu)化指view在ondraw方法中避免大量的耗時(shí)操作荆残,由于ondraw方法可能會(huì)被頻繁的調(diào)用内斯。
1俘闯、ondraw方法中不要?jiǎng)?chuàng)建新的局部變量,ondraw方法被頻繁的調(diào)用萄传,很容易引起GC秀菱。
2衍菱、ondraw方法不要做耗時(shí)操作脊串。
內(nèi)存優(yōu)化:參考內(nèi)存泄漏琼锋。
響應(yīng)優(yōu)化
主線程不能做耗時(shí)操作缕坎,觸摸事件5s,廣播10s谜叹,service20s荷腊。
listview優(yōu)化:
1女仰、getview方法中避免耗時(shí)操作董栽。
2锭碳、view的復(fù)用和viewholder的使用勿璃。
3补疑、滑動(dòng)不適合開啟異步加載莲组。
4锹杈、分頁處理數(shù)據(jù)竭望。
5咬清、圖片使用三級(jí)緩存旧烧。
Bitmap優(yōu)化:
1掘剪、等比例壓縮圖片杖小。
2、不用的圖片浪册,及時(shí)recycler掉
線程優(yōu)化
線程優(yōu)化的思想是使用線程池來管理和復(fù)用線程村象,避免程序中有大量的Thread厚者,同時(shí)可以控制線程的并發(fā)數(shù)库菲,避免相互搶占資源而導(dǎo)致線程阻塞熙宇。
其他優(yōu)化
1烫止、少用枚舉馆蠕,枚舉占用空間大荆几。
2吨铸、使用Android特有的數(shù)據(jù)結(jié)構(gòu)诞吱,如SparseArray來代替hashMap房维。
3咙俩、適當(dāng)?shù)氖褂密浺煤腿跻谩?/p>
加密算法(base64阿趁、MD5脖阵、對(duì)稱加密和非對(duì)稱加密)和使用場景命黔。
什么是Rsa加密蘑辑?
RSA算法是最流行的公鑰密碼算法洋魂,使用長度可以變化的密鑰忧设。RSA是第一個(gè)既能用于數(shù)據(jù)加密也能用于數(shù)字簽名的算法。
RSA算法原理如下:
1.隨機(jī)選擇兩個(gè)大質(zhì)數(shù)p和q顿锰,p不等于q硼控,計(jì)算N=pq牢撼;?
2.選擇一個(gè)大于1小于N的自然數(shù)e熏版,e必須與(p-1)(q-1)互素撼短。?
3.用公式計(jì)算出d:d×e = 1 (mod (p-1)(q-1)) 挺勿。
4.銷毀p和q曲横。
最終得到的N和e就是“公鑰”,d就是“私鑰”不瓶,發(fā)送方使用N去加密數(shù)據(jù)禾嫉,接收方只有使用d才能解開數(shù)據(jù)內(nèi)容灾杰。
RSA的安全性依賴于大數(shù)分解,小于1024位的N已經(jīng)被證明是不安全的夭织,而且由于RSA算法進(jìn)行的都是大數(shù)計(jì)算,使得RSA最快的情況也比DES慢上倍尊惰,這是RSA最大的缺陷讲竿,因此通常只能用于加密少量數(shù)據(jù)或者加密密鑰,但RSA仍然不失為一種高強(qiáng)度的算法弄屡。
使用場景:項(xiàng)目中除了登陸题禀,支付等接口采用rsa非對(duì)稱加密,之外的采用aes對(duì)稱加密膀捷,今天我們來認(rèn)識(shí)一下aes加密迈嘹。
什么是MD5加密?
?? ? MD5英文全稱“Message-Digest Algorithm 5”全庸,翻譯過來是“消息摘要算法5”秀仲,由MD2、MD3壶笼、MD4演變過來的神僵,是一種單向加密算法,是不可逆的一種的加密方式覆劈。
MD5加密有哪些特點(diǎn)保礼?
壓縮性:任意長度的數(shù)據(jù),算出的MD5值長度都是固定的责语。
容易計(jì)算:從原數(shù)據(jù)計(jì)算出MD5值很容易炮障。
抗修改性:對(duì)原數(shù)據(jù)進(jìn)行任何改動(dòng),哪怕只修改1個(gè)字節(jié)坤候,所得到的MD5值都有很大區(qū)別胁赢。
強(qiáng)抗碰撞:已知原數(shù)據(jù)和其MD5值,想找到一個(gè)具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的白筹。
MD5應(yīng)用場景:
一致性驗(yàn)證
數(shù)字簽名
安全訪問認(rèn)證
什么是aes加密智末?
?高級(jí)加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard,縮寫:AES)遍蟋,在密碼學(xué)中又稱Rijndael加密法吹害,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES虚青,已經(jīng)被多方分析且廣為全世界所使用它呀。
HashMap的實(shí)現(xiàn)原理:
HashMap是基于哈希表的map接口的非同步實(shí)現(xiàn),它允許使用null值作為key和value。在Java編程語言中最基本的結(jié)構(gòu)就是兩種纵穿,一種是數(shù)組下隧,另一種是模擬指針(引用)。所有的數(shù)據(jù)結(jié)構(gòu)都可以用這兩個(gè)基本的結(jié)構(gòu)來構(gòu)造谓媒,HashMap也不例外淆院。HashMap實(shí)際上是一個(gè)“鏈表散列”的數(shù)據(jù)結(jié)構(gòu)。即數(shù)組和鏈表的結(jié)合體句惯。
need-to-insert-img
從圖上可以看出土辩,HashMap底層就是一個(gè)數(shù)據(jù)結(jié)構(gòu),數(shù)組中的每一項(xiàng)又是一個(gè)鏈表抢野。
沖突:
HashMap中調(diào)用Hashcode()方法計(jì)算Hashclde值拷淘,由于Java中兩個(gè)不同的對(duì)象可能有一樣的Hashcode。就導(dǎo)致了沖突的產(chǎn)生指孤。
解決:
HashMap在put時(shí)候启涯,底層源碼可以看出,當(dāng)程序試圖將一個(gè)key-value對(duì)象放入到HashMap中恃轩,首先根據(jù)該key的hashCode()返回值決定該Entry的存儲(chǔ)位置结洼,如果兩個(gè)Entry的key的hashCode()方法返回值相同,那他們的存儲(chǔ)位置相同叉跛,如果這兩個(gè)Entry的key通過equals比較返回true松忍,新添加的Entry的value將會(huì)覆蓋原來的Entry的value,但是key不會(huì)被覆蓋昧互,反之挽铁,如果返回false伟桅,新添加的Entry將與集合中原有的Entry形成Entry鏈敞掘,新添加的位于頭部,舊的位于尾部楣铁。
存:
need-to-insert-img
染裂恪:
need-to-insert-img
HashMap的實(shí)現(xiàn)原理:
利用key的hashCode重新hash計(jì)算出當(dāng)前對(duì)象的元素在數(shù)組中的下標(biāo)。
存儲(chǔ)時(shí)如果出現(xiàn)hash值相同的key盖腕,分兩種情況:1赫冬、如果key相同,則覆蓋原來的值溃列。2劲厌、如果key不同(出現(xiàn)沖突),則放在鏈表中听隐。
獲取時(shí)补鼻,直接找到hash值對(duì)應(yīng)的下標(biāo),再進(jìn)一步判斷key是否相同,從而拿到對(duì)應(yīng)的值风范。
Hashmap的核心就是使用數(shù)組進(jìn)行存儲(chǔ)咨跌,出現(xiàn)key沖突的時(shí)候,就存放在鏈表中硼婿。