數(shù)據(jù)類型相關(guān)
java中int char,long各占多少字節(jié)?
|類型|位數(shù)|字節(jié)數(shù)| |-|-|-| |short|2|16| |int|4|32| |long|8|64| |float|4|32 |double|8|64| |char|2|16|
Java 中,int 類型變量的長度是一個(gè)固定值屑咳,與平臺(tái)無關(guān)茅主,都是 32 位水醋。意思就是說,在 32 位 和 64 位 的Java 虛擬機(jī)中伊诵,int 類型的長度是相同的又跛。
Integer是int的包裝類型,在拆箱和裝箱中,而知自動(dòng)轉(zhuǎn)換.int是基本類型嗦董,直接存數(shù)值,而integer是對(duì)象峡眶,用一個(gè)引用指向這個(gè)對(duì)象.
Integer 對(duì)象會(huì)占用更多的內(nèi)存剧防。Integer是一個(gè)對(duì)象,需要存儲(chǔ)對(duì)象的元數(shù)據(jù)辫樱。但是 int 是一個(gè)原始類型的數(shù)據(jù)峭拘,所以占用的空間更少。
String,StringBuffer和StringBuilder區(qū)別
String是字符串常量,final修飾;StringBuffer字符串變量(線程安全); StringBuilder 字符串變量(線程不安全).
String和StringBuffer主要區(qū)別是性能:String是不可變對(duì)象,每次對(duì)String類型進(jìn)行操作都等同于產(chǎn)生了一個(gè)新的String對(duì)象,然后指向新的String對(duì)象.所以盡量不在對(duì)String進(jìn)行大量的拼接操作,否則會(huì)產(chǎn)生很多臨時(shí)對(duì)象,導(dǎo)致GC開始工作,影響系統(tǒng)性能.
StringBuffer是對(duì)對(duì)象本身操作,而不是產(chǎn)生新的對(duì)象,因此在通常在有大量拼接的情況下我們建議使用StringBuffer.
但是需要注意現(xiàn)在JVM會(huì)對(duì)String拼接做一定的優(yōu)化:String s=“This is only ”+”simple”+”test”會(huì)被虛擬機(jī)直接優(yōu)化成String s=“This is only simple test”,此時(shí)就不存在拼接過程.
StringBuffer是線程安全的可變字符串,其內(nèi)部實(shí)現(xiàn)是可變數(shù)組.StringBuilder是java 5.0新增的,其功能和StringBuffer類似,但是非線程安全.因此,在沒有多線程問題的前提下,使用StringBuilder會(huì)取得更好的性能.
什么是編譯器常量?使用它有什么風(fēng)險(xiǎn)?
公共靜態(tài)不可變(public static final )變量也就是我們所說的編譯期常量狮暑,這里的 public 可選的鸡挠。實(shí)際上這些變量在編譯時(shí)會(huì)被替換掉,因?yàn)榫幾g器知道這些變量的值搬男,并且知道這些變量在運(yùn)行時(shí)不能改變拣展。這種方式存在的一個(gè)問題是你使用了一個(gè)內(nèi)部的或第三方庫中的公有編譯時(shí)常量,但是這個(gè)值后面被其他人改變了缔逛,但是你的客戶端仍然在使用老的值备埃,甚至你已經(jīng)部署了一個(gè)新的jar姓惑。為了避免這種情況,當(dāng)你在更新依賴 JAR 文件時(shí)按脚,確保重新編譯你的程序于毙。
java當(dāng)中使用什么類型表示價(jià)格比較好?
如果不是特別關(guān)心內(nèi)存和性能的話,使用BigDecimal辅搬,否則使用預(yù)定義精度的 double 類型唯沮。
可以使用 String 接收 byte[] 參數(shù)的構(gòu)造器來進(jìn)行轉(zhuǎn)換,需要注意的點(diǎn)是要使用的正確的編碼堪遂,否則會(huì)使用平臺(tái)默認(rèn)編碼介蛉,這個(gè)編碼可能跟原來的編碼相同,也可能不同蚤氏。
可以將int強(qiáng)轉(zhuǎn)為byte類型么?會(huì)產(chǎn)生什么問題?
我們可以做強(qiáng)制轉(zhuǎn)換甘耿,但是Java中int是32位的而byte是8 位的,所以,如果強(qiáng)制轉(zhuǎn)化int類型的高24位將會(huì)被丟棄竿滨,byte 類型的范圍是從-128.到128
垃圾回收從理論上非常容易理解,具體的方法有以下幾種:
標(biāo)記-清除
標(biāo)記-復(fù)制
標(biāo)記-整理
分代回收 更詳細(xì)的內(nèi)容參見深入理解垃圾回收算法
如何判斷一個(gè)對(duì)象是否應(yīng)該被回收
這就是所謂的對(duì)象存活性判斷,常用的方法有兩種:1.引用計(jì)數(shù)法;2:對(duì)象可達(dá)性分析.由于引用計(jì)數(shù)法存在互相引用導(dǎo)致無法進(jìn)行GC的問題,所以目前JVM虛擬機(jī)多使用對(duì)象可達(dá)性分析算法.
Java 垃圾回收機(jī)制最基本的做法是分代回收佳恬。內(nèi)存中的區(qū)域被劃分成不同的世代,對(duì)象根據(jù)其存活的時(shí)間被保存在對(duì)應(yīng)世代的區(qū)域中于游。一般的實(shí)現(xiàn)是劃分成3個(gè)世代:年輕毁葱、年老和永久。內(nèi)存的分配是發(fā)生在年輕世代中的贰剥。當(dāng)一個(gè)對(duì)象存活時(shí)間足夠長的時(shí)候倾剿,它就會(huì)被復(fù)制到年老世代中。對(duì)于不同的世代可以使用不同的垃圾回收算法蚌成。進(jìn)行世代劃分的出發(fā)點(diǎn)是對(duì)應(yīng)用中對(duì)象存活時(shí)間進(jìn)行研究之后得出的統(tǒng)計(jì)規(guī)律前痘。一般來說,一個(gè)應(yīng)用中的大部分對(duì)象的存活時(shí)間都很短担忧。比如局部變量的存活時(shí)間就只在方法的執(zhí)行過程中芹缔。基于這一點(diǎn)瓶盛,對(duì)于年輕世代的垃圾回收算法就可以很有針對(duì)性.
調(diào)用System.gc()會(huì)發(fā)生什么?
通知GC開始工作,但是GC真正開始的時(shí)間不確定.
簡而言之,進(jìn)程是程序運(yùn)行和資源分配的基本單位,一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程.進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存資源,減少切換次數(shù),從而效率更高.線程是進(jìn)程的一個(gè)實(shí)體,是cpu調(diào)度和分派的基本單位,是比程序更小的能獨(dú)立運(yùn)行的基本單位.同一進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行.
你了解守護(hù)線程嗎?它和非守護(hù)線程有什么區(qū)別
程序運(yùn)行完畢,jvm會(huì)等待非守護(hù)線程完成后關(guān)閉,但是jvm不會(huì)等待守護(hù)線程.守護(hù)線程最典型的例子就是GC線程
多線程的上下文切換是指CPU控制權(quán)由一個(gè)已經(jīng)正在運(yùn)行的線程切換到另外一個(gè)就緒并等待獲取CPU執(zhí)行權(quán)的線程的過程最欠。
創(chuàng)建兩種線程的方式?他們有什么區(qū)別?
通過實(shí)現(xiàn)java.lang.Runnable或者通過擴(kuò)展java.lang.Thread類.相比擴(kuò)展Thread,實(shí)現(xiàn)Runnable接口可能更優(yōu).原因有二:
Java不支持多繼承.因此擴(kuò)展Thread類就代表這個(gè)子類不能擴(kuò)展其他類.而實(shí)現(xiàn)Runnable接口的類還可能擴(kuò)展另一個(gè)類.
類可能只要求可執(zhí)行即可,因此集成整個(gè)Thread類的開銷過大.
Runnable接口中的run()方法的返回值是void,它做的事情只是純粹地去執(zhí)行run()方法中的代碼而已惩猫;Callable接口中的call()方法是有返回值的芝硬,是一個(gè)泛型,和Future轧房、FutureTask配合可以用來獲取異步執(zhí)行的結(jié)果拌阴。 這其實(shí)是很有用的一個(gè)特性,因?yàn)槎嗑€程相比單線程更難奶镶、更復(fù)雜的一個(gè)重要原因就是因?yàn)槎嗑€程充滿著未知性皮官,某條線程是否執(zhí)行了脯倒?某條線程執(zhí)行了多久?某條線程執(zhí)行的時(shí)候我們期望的數(shù)據(jù)是否已經(jīng)賦值完畢捺氢?無法得知藻丢,我們能做的只是等待這條多線程的任務(wù)執(zhí)行完畢而已。而Callable+Future/FutureTask卻可以獲取多線程運(yùn)行的結(jié)果摄乒,可以在等待時(shí)間太長沒獲取到需要的數(shù)據(jù)的情況下取消該線程的任務(wù)悠反,真的是非常有用。
阻塞指的是暫停一個(gè)線程的執(zhí)行以等待某個(gè)條件發(fā)生(如某資源就緒)馍佑,學(xué)過操作系統(tǒng)的同學(xué)對(duì)它一定已經(jīng)很熟悉了斋否。Java 提供了大量方法來支持阻塞,下面讓我們逐一分析拭荤。
方法說明
sleep()sleep() 允許 指定以毫秒為單位的一段時(shí)間作為參數(shù)茵臭,它使得線程在指定的時(shí)間內(nèi)進(jìn)入阻塞狀態(tài),不能得到CPU 時(shí)間舅世,指定的時(shí)間一過旦委,線程重新進(jìn)入可執(zhí)行狀態(tài)。 典型地雏亚,sleep() 被用在等待某個(gè)資源就緒的情形:測試發(fā)現(xiàn)條件不滿足后缨硝,讓線程阻塞一段時(shí)間后重新測試,直到條件滿足為止
suspend() 和 resume()兩個(gè)方法配套使用罢低,suspend()使得線程進(jìn)入阻塞狀態(tài)查辩,并且不會(huì)自動(dòng)恢復(fù),必須其對(duì)應(yīng)的resume() 被調(diào)用网持,才能使得線程重新進(jìn)入可執(zhí)行狀態(tài)宜岛。典型地,suspend() 和 resume() 被用在等待另一個(gè)線程產(chǎn)生的結(jié)果的情形:測試發(fā)現(xiàn)結(jié)果還沒有產(chǎn)生后功舀,讓線程阻塞谬返,另一個(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è)線程
wait() 和 notify()兩個(gè)方法配套使用瘫絮,wait() 使得線程進(jìn)入阻塞狀態(tài)涨冀,它有兩種形式,一種允許 指定以毫秒為單位的一段時(shí)間作為參數(shù)麦萤,另一種沒有參數(shù)鹿鳖,前者當(dāng)對(duì)應(yīng)的 notify() 被調(diào)用或者超出指定時(shí)間時(shí)線程重新進(jìn)入可執(zhí)行狀態(tài)扁眯,后者則必須對(duì)應(yīng)的 notify() 被調(diào)用.
wait(),notify()和suspend(),resume()之間的區(qū)別
初看起來它們與 suspend() 和 resume() 方法對(duì)沒有什么分別,但是事實(shí)上它們是截然不同的翅帜。區(qū)別的核心在于姻檀,前面敘述的所有方法,阻塞時(shí)都不會(huì)釋放占用的鎖(如果占用了的話)涝滴,而這一對(duì)方法則相反绣版。上述的核心區(qū)別導(dǎo)致了一系列的細(xì)節(jié)上的區(qū)別。
首先歼疮,前面敘述的所有方法都隸屬于 Thread 類杂抽,但是這一對(duì)卻直接隸屬于 Object 類,也就是說韩脏,所有對(duì)象都擁有這一對(duì)方法缩麸。初看起來這十分不可思議,但是實(shí)際上卻是很自然的赡矢,因?yàn)檫@一對(duì)方法阻塞時(shí)要釋放占用的鎖杭朱,而鎖是任何對(duì)象都具有的,調(diào)用任意對(duì)象的 wait() 方法導(dǎo)致線程阻塞济竹,并且該對(duì)象上的鎖被釋放痕檬。而調(diào)用 任意對(duì)象的notify()方法則導(dǎo)致因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選擇的一個(gè)解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。
其次送浊,前面敘述的所有方法都可在任何位置調(diào)用梦谜,但是這一對(duì)方法卻必須在 synchronized 方法或塊中調(diào)用,理由也很簡單袭景,只有在synchronized 方法或塊中當(dāng)前線程才占有鎖唁桩,才有鎖可以釋放。同樣的道理耸棒,調(diào)用這一對(duì)方法的對(duì)象上的鎖必須為當(dāng)前線程所擁有荒澡,這樣才有鎖可以釋放。因此与殃,這一對(duì)方法調(diào)用必須放置在這樣的 synchronized 方法或塊中单山,該方法或塊的上鎖對(duì)象就是調(diào)用這一對(duì)方法的對(duì)象。若不滿足這一條件幅疼,則程序雖然仍能編譯米奸,但在運(yùn)行時(shí)會(huì)出現(xiàn)IllegalMonitorStateException 異常。
wait() 和 notify() 方法的上述特性決定了它們經(jīng)常和synchronized 方法或塊一起使用爽篷,將它們和操作系統(tǒng)的進(jìn)程間通信機(jī)制作一個(gè)比較就會(huì)發(fā)現(xiàn)它們的相似性:synchronized方法或塊提供了類似于操作系統(tǒng)原語的功能悴晰,它們的執(zhí)行不會(huì)受到多線程機(jī)制的干擾,而這一對(duì)方法則相當(dāng)于 block 和wakeup 原語(這一對(duì)方法均聲明為 synchronized)。它們的結(jié)合使得我們可以實(shí)現(xiàn)操作系統(tǒng)上一系列精妙的進(jìn)程間通信的算法(如信號(hào)量算法)铡溪,并用于解決各種復(fù)雜的線程間通信問題漂辐。
關(guān)于 wait() 和 notify() 方法最后再說明兩點(diǎn): 第一:調(diào)用 notify() 方法導(dǎo)致解除阻塞的線程是從因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選取的,我們無法預(yù)料哪一個(gè)線程將會(huì)被選擇棕硫,所以編程時(shí)要特別小心髓涯,避免因這種不確定性而產(chǎn)生問題。
第二:除了 notify()饲帅,還有一個(gè)方法 notifyAll() 也可起到類似作用复凳,唯一的區(qū)別在于,調(diào)用 notifyAll() 方法將把因調(diào)用該對(duì)象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞灶泵。當(dāng)然育八,只有獲得鎖的那一個(gè)線程才能進(jìn)入可執(zhí)行狀態(tài)。
談到阻塞赦邻,就不能不談一談死鎖髓棋,略一分析就能發(fā)現(xiàn),suspend() 方法和不指定超時(shí)期限的 wait() 方法的調(diào)用都可能產(chǎn)生死鎖惶洲。遺憾的是按声,Java 并不在語言級(jí)別上支持死鎖的避免,我們?cè)诰幊讨斜仨毿⌒牡乇苊馑梨i恬吕。
以上我們對(duì) Java 中實(shí)現(xiàn)線程阻塞的各種方法作了一番分析签则,我們重點(diǎn)分析了 wait() 和 notify() 方法,因?yàn)樗鼈兊墓δ茏顝?qiáng)大铐料,使用也最靈活渐裂,但是這也導(dǎo)致了它們的效率較低,較容易出錯(cuò)钠惩。實(shí)際使用中我們應(yīng)該靈活使用各種方法柒凉,以便更好地達(dá)到我們的目的。
為什么wait()方法和notify()/notifyAll()方法要在同步塊中被調(diào)用
這是JDK強(qiáng)制的篓跛,wait()方法和notify()/notifyAll()方法在調(diào)用前都必須先獲得對(duì)象的鎖
wait()方法和notify()/notifyAll()方法在放棄對(duì)象監(jiān)視器時(shí)有什么區(qū)別
wait()方法和notify()/notifyAll()方法在放棄對(duì)象監(jiān)視器的時(shí)候的區(qū)別在于:wait()方法立即釋放對(duì)象監(jiān)視器膝捞,notify()/notifyAll()方法則會(huì)等待線程剩余代碼執(zhí)行完畢才會(huì)放棄對(duì)象監(jiān)視器。
關(guān)于這兩者已經(jīng)在上面進(jìn)行詳細(xì)的說明,這里就做個(gè)概括好了:
sleep()來自Thread類愧沟,和wait()來自O(shè)bject類.調(diào)用sleep()方法的過程中蔬咬,線程不會(huì)釋放對(duì)象鎖。而 調(diào)用 wait 方法線程會(huì)釋放對(duì)象鎖
sleep()睡眠后不出讓系統(tǒng)資源沐寺,wait讓其他線程可以占用CPU
sleep(milliseconds)需要指定一個(gè)睡眠時(shí)間林艘,時(shí)間一到會(huì)自動(dòng)喚醒.而wait()需要配合notify()或者notifyAll()使用
synchronized和ReentrantLock的區(qū)別
synchronized是和if、else芽丹、for、while一樣的關(guān)鍵字卜朗,ReentrantLock是類拔第,這是二者的本質(zhì)區(qū)別咕村。既然ReentrantLock是類,那么它就提供了比synchronized更多更靈活的特性蚊俺,可以被繼承懈涛、可以有方法、可以有各種各樣的類變量泳猬,ReentrantLock比synchronized的擴(kuò)展性體現(xiàn)在幾點(diǎn)上: (1)ReentrantLock可以對(duì)獲取鎖的等待時(shí)間進(jìn)行設(shè)置批钠,這樣就避免了死鎖 (2)ReentrantLock可以獲取各種鎖的信息 (3)ReentrantLock可以靈活地實(shí)現(xiàn)多路通知 另外,二者的鎖機(jī)制其實(shí)也是不一樣的:ReentrantLock底層調(diào)用的是Unsafe的park方法加鎖得封,synchronized操作的應(yīng)該是對(duì)象頭中mark word.
好了同學(xué)們埋心,我能介紹的也都全部介紹完給你們了,如果下獲得更多JAVA教學(xué)資源忙上,可以選擇來我們這里共同交流拷呆,群:240448376,很多大神在這里切磋學(xué)習(xí)疫粥,不懂可以直接問茬斧,晚上還有大牛免費(fèi)直播教學(xué)。
注:加群要求
1梗逮、具有一定工作經(jīng)驗(yàn)的项秉,面對(duì)目前流行的技術(shù)不知從何下手,需要突破技術(shù)瓶頸的可以加慷彤,有些應(yīng)屆生和實(shí)習(xí)生也可以加娄蔼。
2、在公司待久了瞬欧,過得很安逸贷屎,但跳槽時(shí)面試碰壁。需要在短時(shí)間內(nèi)進(jìn)修艘虎、跳槽拿高薪的可以加唉侄。
3、如果沒有工作經(jīng)驗(yàn)野建,但基礎(chǔ)非常扎實(shí)属划,對(duì)java工作機(jī)制,常用設(shè)計(jì)思想候生,常用java開發(fā)框架掌握熟練的同眯,可以加甚亭。
4函筋、覺得自己很牛B,一般需求都能搞定铛楣。但是所學(xué)的知識(shí)點(diǎn)沒有系統(tǒng)化,很難在技術(shù)領(lǐng)域繼續(xù)突破的可以加明肮。
5.阿里Java高級(jí)大牛直播講解知識(shí)點(diǎn)菱农,分享知識(shí),多年工作經(jīng)驗(yàn)的梳理和總結(jié)柿估,帶著大家全面循未、科學(xué)地建立自己的技術(shù)體系和技術(shù)認(rèn)知!
PS:現(xiàn)在主要講解的內(nèi)容是(反射原理秫舌、枚舉原理與應(yīng)用的妖、注解原理、常用設(shè)計(jì)模式足陨、正規(guī)表達(dá)式高級(jí)應(yīng)用嫂粟、JAVA操作Office原理詳解、JAVA圖像處理技術(shù)钠右,等多個(gè)知識(shí)點(diǎn)的詳解和實(shí)戰(zhàn))
6.小號(hào)或者小白之類加群一律不給過赋元,謝謝。
最后飒房,每一位讀到這里的網(wǎng)友搁凸,感謝你們能耐心地看完。覺得對(duì)你有幫助可以給個(gè)喜歡狠毯!希望在成為一名更優(yōu)秀的Java程序員的道路上护糖,我們可以一起學(xué)習(xí)、一起進(jìn)步