新聞中心
[[280850]]

1、開(kāi)啟線程的三種方式?
1)繼承Thread類(lèi),重寫(xiě)run()方法,在run()方法體中編寫(xiě)要完成的任務(wù) new Thread().start();
2)實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)run()方法 new Thread(new MyRunnable()).start();
3)實(shí)現(xiàn)Callable接口MyCallable類(lèi),實(shí)現(xiàn)call()方法,使用FutureTask類(lèi)來(lái)包裝Callable對(duì)象,使用FutureTask對(duì)象作為T(mén)hread對(duì)象的target創(chuàng)建并啟動(dòng)線程;調(diào)用FutureTask對(duì)象的get()方法來(lái)獲得子線程執(zhí)行結(jié)束后的返回值。
- FutureTask
ft = new FutureTask (new MyCallable()); - new Thread(ft).start();
2、run()和start()方法區(qū)別
run()方法只是線程的主體方法,和普通方法一樣,不會(huì)創(chuàng)建新的線程。只有調(diào)用start()方法,才會(huì)啟動(dòng)一個(gè)新的線程,新線程才會(huì)調(diào)用run()方法,線程才會(huì)開(kāi)始執(zhí)行。
3、如何控制某個(gè)方法允許并發(fā)訪問(wèn)線程的個(gè)數(shù)?
創(chuàng)建Semaphore變量,Semaphore semaphore = new Semaphore(5, true); 當(dāng)方法進(jìn)入時(shí),請(qǐng)求一個(gè)信號(hào),如果信號(hào)被用完則等待,方法運(yùn)行完,釋放一個(gè)信號(hào),釋放的信號(hào)新的線程就可以使用。
4、在Java中wait和seelp方法的不同
wait()方法屬于Object類(lèi),調(diào)用該方法時(shí),線程會(huì)放棄對(duì)象鎖,只有該對(duì)象調(diào)用notify()方法后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備獲取對(duì)象鎖進(jìn)入運(yùn)行狀態(tài)。
sleep()方法屬于Thread類(lèi),sleep()導(dǎo)致程序暫停執(zhí)行指定的時(shí)間,讓出CPU,但它的監(jiān)控狀態(tài)依然保存著,當(dāng)指定時(shí)間到了又會(huì)回到運(yùn)行狀態(tài),sleep()方法中線程不會(huì)釋放對(duì)象鎖。
5、談?wù)剋ait/notify關(guān)鍵字的理解
notify: 喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程
notifyAll(): 通知所有等待該競(jìng)爭(zhēng)資源的線程
wait: 釋放obj的鎖,導(dǎo)致當(dāng)前的線程等待,直接其他線程調(diào)用此對(duì)象的notify()或notifyAll()方法
當(dāng)要調(diào)用wait()或notify()/notifyAll()方法時(shí),一定要對(duì)競(jìng)爭(zhēng)資源進(jìn)行加鎖,一般放到synchronized(obj)代碼中。
當(dāng)調(diào)用obj.notify/notifyAll后,調(diào)用線程依舊持有obj鎖,因此等待線程雖被喚醒,但仍無(wú)法獲得obj鎖,直到調(diào)用線程退出synchronized塊,釋放obj鎖后,其他等待線程才有機(jī)會(huì)獲得鎖繼續(xù)執(zhí)行
6、什么導(dǎo)致線程阻塞?
一般線程阻塞
1)線程執(zhí)行了Thread.sleep(int millsecond)方法,放棄CPU,睡眠一段時(shí)間,一段時(shí)間過(guò)后恢復(fù)執(zhí)行;
2)線程執(zhí)行一段同步代碼,但無(wú)法獲得相關(guān)的同步鎖,只能進(jìn)入阻塞狀態(tài),等到獲取到同步鎖,才能恢復(fù)執(zhí)行;
3)線程執(zhí)行了一個(gè)對(duì)象的wait()方法,直接進(jìn)入阻塞態(tài),等待其他線程執(zhí)行notify()/notifyAll()操作;
4)線程執(zhí)行某些IO操作,因?yàn)榈却嚓P(guān)資源而進(jìn)入了阻塞態(tài),如System.in,但沒(méi)有收到鍵盤(pán)的輸入,則進(jìn)入阻塞態(tài)。
5)線程禮讓?zhuān)琓hread.yield()方法,暫停當(dāng)前正在執(zhí)行的線程對(duì)象,把執(zhí)行機(jī)會(huì)讓給相同或更高優(yōu)先級(jí)的線程,但并不會(huì)使線程進(jìn)入阻塞態(tài),線程仍處于可執(zhí)行態(tài),隨時(shí)可能再次分得CPU時(shí)間。
線程自閉,join()方法,在當(dāng)前線程調(diào)用另一個(gè)線程的join()方法,則當(dāng)前線程進(jìn)入阻塞態(tài),直到另一個(gè)線程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒態(tài)。
6)線程執(zhí)行suspend()使線程進(jìn)入阻塞態(tài),必須resume()方法被調(diào)用,才能使線程重新進(jìn)入可執(zhí)行狀態(tài)
7?線程如何關(guān)閉?
1 ) 使用標(biāo)志位
2)使用stop()方法,但該方法就像關(guān)掉電腦電源一樣,可能會(huì)發(fā)生預(yù)料不到的問(wèn)題
3)使用中斷interrupt()
- public class Thread {
- // 中斷當(dāng)前線程
- public void interrupt();
- // 判斷當(dāng)前線程是否被中斷
- public boolen isInterrupt();
- // 清除當(dāng)前線程的中斷狀態(tài),并返回之前的值
- public static boolen interrupted();
- }
但調(diào)用interrupt()方法只是傳遞中斷請(qǐng)求消息,并不代表要立馬停止目標(biāo)線程。
8、講一下java中的同步的方法
之所以需要同步,因?yàn)樵诙嗑€程并發(fā)控制,當(dāng)多個(gè)線程同時(shí)操作一個(gè)可共享的資源時(shí),如果沒(méi)有采取同步機(jī)制,將會(huì)導(dǎo)致數(shù)據(jù)不準(zhǔn)確,因此需要加入同步鎖,確保在該線程沒(méi)有完成操作前被其他線程調(diào)用,從而保證該變量的唯一一性和準(zhǔn)確性。
1)synchronized修飾同步代碼塊或方法
由于java的每個(gè)對(duì)象都有一個(gè)內(nèi)置鎖,用此關(guān)鍵字修飾方法時(shí),內(nèi)置鎖會(huì)保護(hù)整個(gè)方法。在調(diào)用該方法前,需獲得內(nèi)置鎖,否則就處于陰塞狀態(tài)。
2)volatile修飾變量
保證變量在線程間的可見(jiàn)性,每次線程要訪問(wèn)volatile修飾的變量時(shí)都從內(nèi)存中讀取,而不緩存中,這樣每個(gè)線程訪問(wèn)到的變量都是一樣的。且使用內(nèi)存屏障。
3)ReentrantLock重入鎖,它常用的方法有ReentrantLock():創(chuàng)建一個(gè)ReentrantLock實(shí)例
lock()獲得鎖 unlock()釋放鎖
4)使用局部變量ThreadLocal實(shí)現(xiàn)線程同步,每個(gè)線程都會(huì)保存一份該變量的副本,副本之間相互獨(dú)立,這樣每個(gè)線程都可以隨意修改自己的副本,而不影響其他線程。
常用方法ThreadLocal()創(chuàng)建一個(gè)線程本地變量;get()返回此線程局部的當(dāng)前線程副本變量;initialValue()返回此線程局部變量的當(dāng)前線程的初始值;set(T value)將此線程變量的當(dāng)前線程副本中的值設(shè)置為value
使用原子變量,如AtomicInteger,常用方法AtomicInteger(int value)創(chuàng)建個(gè)有給定初始值的AtomicInteger整數(shù);addAndGet(int data)以原子方式將給定值與當(dāng)前值相加
6)使用阻塞隊(duì)列實(shí)現(xiàn)線程同步LinkedBlockingQueue
9、如何保證線程安全?
線程安全性體現(xiàn)在三方法:
1)原子性:提供互斥訪問(wèn),同一時(shí)刻只能有一個(gè)線和至數(shù)據(jù)進(jìn)行操作。
JDK中提供了很多atomic類(lèi),如AtomicInteger\AtomicBoolean\AtomicLong,它們是通過(guò)CAS完成原子性。JDK提供鎖分為兩種:synchronized依賴(lài)JVM實(shí)現(xiàn)鎖,該關(guān)鍵字作用對(duì)象的作用范圍內(nèi)同一時(shí)刻只能有一個(gè)線程進(jìn)行操作。另一種是LOCK,是JDK提供的
代碼層面的鎖,依賴(lài)CPU指令,代表性是ReentrantLock。
2)可見(jiàn)性:一個(gè)線程對(duì)主內(nèi)存的修改及時(shí)被其他線程看到。
JVM提供了synchronized和volatile,volatile的可見(jiàn)性是通過(guò)內(nèi)存屏障和禁止重排序?qū)崿F(xiàn)的,volatile會(huì)在寫(xiě)操作時(shí),在寫(xiě)操作后加一條store屏障指令,將本地內(nèi)存中的共享變量值刷新到主內(nèi)存;會(huì)在讀操作時(shí),在讀操作前加一條load指令,從內(nèi)存中讀取共享變量。
3)有序性:指令沒(méi)有被編譯器重排序。
可通過(guò)volatile、synchronized、Lock保證有序性。
10、兩個(gè)進(jìn)程同時(shí)要求寫(xiě)或者讀,能不能實(shí)現(xiàn)?如何防止進(jìn)程的同步?
我認(rèn)為可以實(shí)現(xiàn),比如兩個(gè)進(jìn)程都讀取日歷進(jìn)程數(shù)據(jù)是沒(méi)有問(wèn)題,但同時(shí)寫(xiě),應(yīng)該會(huì)有沖突。
可以使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間數(shù)據(jù)共享。
11、線程間操作List
12、Java中對(duì)象的生命周期
1)創(chuàng)建階段(Created):為對(duì)象分配存儲(chǔ)空間,開(kāi)始構(gòu)造對(duì)象,從超類(lèi)到子類(lèi)對(duì)static成員初始化;超類(lèi)成員變量按順序初始化,遞歸調(diào)用超類(lèi)的構(gòu)造方法,子類(lèi)成員變量按順序初始化,子類(lèi)構(gòu)造方法調(diào)用。
2)應(yīng)用階段(In Use):對(duì)象至少被一個(gè)強(qiáng)引用持有著。
3)不可見(jiàn)階段(Invisible):程序運(yùn)行已超出對(duì)象作用域
4)不可達(dá)階段(Unreachable):該對(duì)象不再被強(qiáng)引用所持有
5)收集階段(Collected):假設(shè)該對(duì)象重寫(xiě)了finalize()方法且未執(zhí)行過(guò),會(huì)去執(zhí)行該方法。
6)終結(jié)階段(Finalized):對(duì)象運(yùn)行完finalize()方法仍處于不可達(dá)狀態(tài),等待垃圾回收器對(duì)該對(duì)象空間進(jìn)行回收。
7)對(duì)象空間重新分配階段(De-allocated):垃圾回收器對(duì)該對(duì)象所占用的內(nèi)存空間進(jìn)行回收或再分配,該對(duì)象徹底消失。
13、static synchronized 方法的多線程訪問(wèn)和作用
static synchronized控制的是類(lèi)的所有實(shí)例訪問(wèn),不管new了多少對(duì)象,只有一份,所以對(duì)該類(lèi)的所有對(duì)象都加了鎖。限制多線程中該類(lèi)的所有實(shí)例同時(shí)訪問(wèn)JVM中該類(lèi)對(duì)應(yīng)的代碼。
14、同一個(gè)類(lèi)里面兩個(gè)synchronized方法,兩個(gè)線程同時(shí)訪問(wèn)的問(wèn)題
如果synchronized修飾的是靜態(tài)方法,鎖的是當(dāng)前類(lèi)的class對(duì)象,進(jìn)入同步代碼前要獲得當(dāng)前類(lèi)對(duì)象的鎖;
普通方法,鎖的是當(dāng)前實(shí)例對(duì)象,進(jìn)入同步代碼前要獲得的是當(dāng)前實(shí)例的鎖;
同步代碼塊,鎖的是括號(hào)里面的對(duì)象,對(duì)給定的對(duì)象加鎖,進(jìn)入同步代碼塊庫(kù)前要獲得給定對(duì)象鎖;
如果兩個(gè)線程訪問(wèn)同一個(gè)對(duì)象的synchronized方法,會(huì)出現(xiàn)競(jìng)爭(zhēng),如果是不同對(duì)象,則不會(huì)相互影響。
15、volatile的原理
有volatile變量修飾的共享變量進(jìn)行寫(xiě)操作的時(shí)候會(huì)多一條匯編代碼,lock addl $0x0,lock前綴的指令在多核處理器下會(huì)將當(dāng)前處理器緩存行的數(shù)據(jù)會(huì)寫(xiě)回到系統(tǒng)內(nèi)存,這個(gè)寫(xiě)回內(nèi)存的操作會(huì)引起在其他CPU里緩存了該內(nèi)存地址的數(shù)據(jù)無(wú)效。同時(shí)lock前綴也相當(dāng)于一個(gè)內(nèi)存屏障,對(duì)內(nèi)存操作順序進(jìn)行了限制。
16、synchronized原理
synchronized通過(guò)對(duì)象的對(duì)象頭(markword)來(lái)實(shí)現(xiàn)鎖機(jī)制,java每個(gè)對(duì)象都有對(duì)象頭,都可以為synchronized實(shí)現(xiàn)提供基礎(chǔ),都可以作為鎖對(duì)象,在字節(jié)碼層面synchronized塊是通過(guò)插入monitorenter monitorexit完成同步的。持有monitor對(duì)象,通過(guò)進(jìn)入、退出這個(gè)Monitor對(duì)象來(lái)實(shí)現(xiàn)鎖機(jī)制。
17、談?wù)凬IO的理解
NIO( New Input/ Output) 引入了一種基于通道和緩沖區(qū)的 I/O 方式,它可以使用 Native 函數(shù)庫(kù)直接分配堆外內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在 Java 堆的 DirectByteBuffer 對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作,避免了在 Java 堆和 Native 堆中來(lái)回復(fù)制數(shù)據(jù)。
NIO 是一種同步非阻塞的 IO 模型。同步是指線程不斷輪詢(xún) IO 事件是否就緒,非阻塞是指線程在等待 IO 的時(shí)候,可以同時(shí)做其他任務(wù)。
同步的核心就是 Selector,Selector 代替了線程本身輪詢(xún) IO 事件,避免了阻塞同時(shí)減少了不必要的線程消耗;非阻塞的核心就是通道和緩沖區(qū),當(dāng) IO 事件就緒時(shí),可以通過(guò)寫(xiě)道緩沖區(qū),保證 IO 的成功,而無(wú)需線程阻塞式地等待。
- synchronized 和volatile 關(guān)鍵字的區(qū)別
- synchronized與Lock的區(qū)別
- ReentrantLock 、synchronized和volatile比較
1)volatile:解決變量在多個(gè)線程間的可見(jiàn)性,但不能保證原子性,只能用于修飾變量,不會(huì)發(fā)生阻塞。volatile能屏蔽編譯指令重排,不會(huì)把其后面的指令排到內(nèi)存屏障之前的位置,也不會(huì)把前面的指令排到內(nèi)存屏障的后面。多用于并行計(jì)算的單例模式。volatile規(guī)定CPU每次都必須從內(nèi)存讀取數(shù)據(jù),不能從CPU緩存中讀取,保證了多線程在多CPU計(jì)算中永遠(yuǎn)拿到的都是最新的值。
2)synchronized:互斥鎖,操作互斥,并發(fā)線程過(guò)來(lái),串行獲得鎖,串行執(zhí)行代碼。解決的是多個(gè)線程間訪問(wèn)共享資源的同步性,可保證原子性,也可間接保證可見(jiàn)性,因?yàn)樗鼤?huì)將私有內(nèi)存和公有內(nèi)存中的數(shù)據(jù)做同步??捎脕?lái)修飾方法、代碼塊。會(huì)出現(xiàn)阻塞。synchronized發(fā)生異常時(shí),會(huì)自動(dòng)釋放線程占有的鎖,因此不會(huì)導(dǎo)致死鎖現(xiàn)象發(fā)生。非公平鎖,每次都是相互爭(zhēng)搶資源。
3)lock是一個(gè)接口,而synchronized是java中的關(guān)鍵字,synchronized是內(nèi)置語(yǔ)言的實(shí)現(xiàn)。lock可以讓等待鎖的線程響應(yīng)中斷。在發(fā)生異常時(shí),如果沒(méi)有主動(dòng)通過(guò)unLock()去釋放鎖,則可能造成死鎖現(xiàn)象,因此使用Lock時(shí)需要在finally塊中釋放鎖。
4)ReentrantLock可重入鎖,鎖的分配機(jī)制是基于線程的分配,而不是基于方法調(diào)用的分配。ReentrantLock有tryLock方法,如果鎖被其他線程持有,返回false,可避免形成死鎖。對(duì)代碼加鎖的顆粒會(huì)更小,更節(jié)省資源,提高代碼性能。ReentrantLock可實(shí)現(xiàn)公平鎖和非公平鎖,公平鎖就是先來(lái)的先獲取資源。ReentrantReadWriteLock用于讀多寫(xiě)少的場(chǎng)合,且讀不需要互斥場(chǎng)景。
- ReentrantLock的內(nèi)部實(shí)現(xiàn)
- lock原理
- 死鎖的四個(gè)必要條件?
- 怎么避免死鎖?
- 對(duì)象鎖和類(lèi)鎖是否會(huì)互相影響?
- 什么是線程池,如何使用?
- Java的并發(fā)、多線程、線程模型
- 談?wù)剬?duì)多線程的理解
- 多線程有什么要注意的問(wèn)題?
- 談?wù)勀銓?duì)并發(fā)編程的理解并舉例說(shuō)明
- 談?wù)勀銓?duì)多線程同步機(jī)制的理解?
- 如何保證多線程讀寫(xiě)文件的安全?
- 多線程斷點(diǎn)續(xù)傳原理
- 斷點(diǎn)續(xù)傳的實(shí)現(xiàn)
5)并發(fā)編程有關(guān)知識(shí)點(diǎn)(這個(gè)是一般Android開(kāi)發(fā)用的少的,所以建議多去看看):
平時(shí)Android開(kāi)發(fā)中對(duì)并發(fā)編程可以做得比較少,Thread這個(gè)類(lèi)經(jīng)常會(huì)用到,但是我們想提升自己的話,一定不能停留在表面,,我們也應(yīng)該去了解一下java的關(guān)于線程相關(guān)的源碼級(jí)別的東西。
當(dāng)前名稱(chēng):線程、多線程和線程池,我終于把這些全部搞懂了
URL地址:http://www.fisionsoft.com.cn/article/coiegop.html


咨詢(xún)
建站咨詢(xún)
