『來(lái)源:HollisChuang』
1巧鸭、進(jìn)程和線程的區(qū)別
??進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng)旅薄,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。每一個(gè)進(jìn)程都有一個(gè)自己的地址空間。進(jìn)程具有一定的獨(dú)立功能供炼。
??線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位一屋。線程在程序中是獨(dú)立的并發(fā)的執(zhí)行流。
??線程自己不擁有系統(tǒng)資源袋哼,它與父進(jìn)程的其他線程共享該進(jìn)程所擁有的全部資源冀墨,線程只擁有一點(diǎn)在運(yùn)行中必不可少的資源,比如:自己的堆棧涛贯、自己的程序計(jì)數(shù)器和自己的局部變量诽嘉。
??一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程;同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行。線程的執(zhí)行時(shí)搶占式的弟翘,也就意味著當(dāng)前運(yùn)行的線程在任何時(shí)候都有可能被掛起虫腋,以便另外一個(gè)線程可以運(yùn)行。
?
區(qū)別:
??① 一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程
??② 內(nèi)存共享:進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元(一個(gè)進(jìn)程崩潰后稀余,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響)悦冀;
??而多個(gè)線程共享進(jìn)程提供的內(nèi)存(擁有自己的私有棧空間只是作為運(yùn)行需要的極少內(nèi)存)睛琳,從而極大地提高了程序的運(yùn)行效率雏门,但一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉。所以多進(jìn)程的程序要比多線程的程序健壯
??③ 因?yàn)榫€程的劃分尺度小于進(jìn)程掸掏,使得多線程程序的并發(fā)行高茁影。
??④ 執(zhí)行過(guò)程:進(jìn)程獨(dú)立執(zhí)行;線程不能夠獨(dú)立執(zhí)行丧凤,必須依存在應(yīng)用程序中募闲,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制。
??⑤ 從邏輯角度來(lái)看愿待,多線程的意義在于一個(gè)應(yīng)用程序中浩螺,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行。
??但操作系統(tǒng)并沒(méi)有將多個(gè)線程看做多個(gè)獨(dú)立的應(yīng)用仍侥,來(lái)實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配要出。這就是進(jìn)程和線程的重要區(qū)別。
參考鏈接
https://blog.csdn.net/mxsgoden/article/details/8821936
??
2农渊、并行和并發(fā)的區(qū)別和聯(lián)系
??并行:是指在同一時(shí)刻患蹂,有多條指令在多個(gè)處理器上同時(shí)執(zhí)行。
??并發(fā):是指在同一時(shí)刻只能有一條指令執(zhí)行砸紊,但多個(gè)進(jìn)程指令被快速輪換執(zhí)行传于,使得在宏觀上具有多個(gè)進(jìn)程同時(shí)執(zhí)行的效果。
??
3醉顽、同步和異步
??同步:可以理解為在執(zhí)行完一個(gè)函數(shù)或方法之后沼溜,一直等待系統(tǒng)返回值或消息,這時(shí)程序是出于阻塞的游添,只有接收到返回的值或消息后才往下執(zhí)行其他的命令系草。
??異步:執(zhí)行完函數(shù)或方法后通熄,不必阻塞性地等待返回值或消息,只需要向系統(tǒng)委托一個(gè)異步過(guò)程找都,那么當(dāng)系統(tǒng)接收到返回值或消息時(shí)唇辨,系統(tǒng)會(huì)自動(dòng)觸發(fā)委托的異步過(guò)程,通過(guò)狀態(tài)檐嚣、通知和回調(diào)來(lái)通知調(diào)用者,從而完成一個(gè)完整的流程啰扛。
??同步在一定程度上可以看做是單線程嚎京,這個(gè)線程請(qǐng)求一個(gè)方法后就待這個(gè)方法給他回復(fù),否則他不往下執(zhí)行(死心眼)隐解。
??異步在一定程度上可以看做是多線程的鞍帝,請(qǐng)求一個(gè)方法后,就不管了煞茫,繼續(xù)執(zhí)行其他的方法帕涌,等有返回值以后,再回來(lái)執(zhí)行程序
??
4续徽、多線程的實(shí)現(xiàn)方式蚓曼,有什么區(qū)別
實(shí)現(xiàn)方式:
① 繼承Thread
類
??繼承Thread
類,重寫(xiě)run()
方法钦扭,實(shí)例化線程類纫版,調(diào)用start()
方法啟動(dòng)線程。
??
??
② 實(shí)現(xiàn)Runnable
接口
??實(shí)現(xiàn)Runnable
接口并重寫(xiě)run()
方法客情,創(chuàng)建Runnable
實(shí)例其弊,并以此實(shí)例作為Thread
類的target
參數(shù)創(chuàng)建Thread
對(duì)象,調(diào)用Thread
對(duì)象的start()
啟動(dòng)線程
??
③ 使用Callable
接口和Future
來(lái)創(chuàng)建線程
??
??實(shí)現(xiàn)Callable
接口膀斋,并實(shí)現(xiàn)call()
方法梭伐,并創(chuàng)建Callable
實(shí)例,然后使用FutureTask
對(duì)象來(lái)包裝Callable
實(shí)例仰担,使用FutureTask
對(duì)象作為Thread
的target
來(lái)創(chuàng)建并啟動(dòng)線程
??
區(qū)別:
??Runnable
接口和Callable
接口的方式基本相同(實(shí)現(xiàn)Runnable
接口和Callable
接口僅僅是創(chuàng)建了一個(gè)任務(wù)糊识,但是仍然需要Thread
類來(lái)創(chuàng)建線程并啟動(dòng)),他倆唯一區(qū)別只是Callable
接口實(shí)現(xiàn)方法有返回值,并且也可以聲明拋出異常而已摔蓝,可以歸為一類技掏。
??
1、繼承Thread
實(shí)現(xiàn)線程
??① 已經(jīng)繼承了Thread
類项鬼,不能繼承其他類
??② 獲取當(dāng)前線程哑梳,可以直接使用this
來(lái)獲得
??
2、實(shí)現(xiàn)Runnable
接口绘盟、Callable
接口創(chuàng)建線程
??①實(shí)現(xiàn)的是接口鸠真,還可以繼承其他類
??② 多個(gè)線程可以共享同一個(gè)target
對(duì)象悯仙,適合多個(gè)相同的線程來(lái)處理同一份資源的情況
??③ 獲取當(dāng)前線程必須用Thread.currentThread()
方法來(lái)獲得
http://www.liuzk.com/183.html
??
5、什么叫守護(hù)線程
??在Java中有兩類線程:User Thread(用戶線程)吠卷、Daemon Thread(守護(hù)線程) 锡垄。
??守護(hù)線程, 是指在程序運(yùn)行的時(shí)候在后臺(tái)提供一種通用服務(wù)的線程, 比如垃圾回收線程就是一個(gè)很稱職的守護(hù)者。
??并且這種線程并不屬于程序中不可或缺的部分祭隔。因此只要當(dāng)前JVM實(shí)例中尚存在任何一個(gè)非守護(hù)線程沒(méi)有結(jié)束货岭,守護(hù)線程就全部工作;只有當(dāng)最后一個(gè)非守護(hù)線程結(jié)束時(shí)疾渴,守護(hù)線程隨著JVM一同結(jié)束工作千贯。
??可以通過(guò)調(diào)用線程的setDaemon()
方法,傳入?yún)?shù)true搞坝,將一個(gè)用戶線程設(shè)置為一個(gè)守護(hù)線程
??
這里有幾點(diǎn)需要注意:
??(1) thread.setDaemon()
必須在thread.start()
之前設(shè)置搔谴,否則會(huì)跑出一個(gè)IllegalThreadStateException
異常。你不能把正在運(yùn)行的常規(guī)線程設(shè)置為守護(hù)線程桩撮。
??(2) 在Daemon線程中產(chǎn)生的新線程也是Daemon的敦第。
??(3) 不要認(rèn)為所有的應(yīng)用都可以分配給Daemon來(lái)進(jìn)行服務(wù),比如讀寫(xiě)操作或者計(jì)算邏輯店量。 因?yàn)槟悴豢赡苤涝谒械腢ser完成之前芜果,Daemon是否已經(jīng)完成了預(yù)期的服務(wù)任務(wù)。一旦User退出了融师,可能大量數(shù)據(jù)還沒(méi)有來(lái)得及讀入或?qū)懗鍪δ唬?jì)算任務(wù)也可能多次運(yùn)行結(jié)果不一樣。這對(duì)程序是毀滅性的诬滩。
??
6霹粥、如何停止一個(gè)線程?
??① 設(shè)置一個(gè)標(biāo)志位 需要用volatile
來(lái)修飾疼鸟,保證線程讀取時(shí)標(biāo)志位是最新數(shù)據(jù)
??② 在sleep
狀態(tài)下使用interrupt()
方法后控,程序拋出InterruptedException
,捕捉這個(gè)異常來(lái)結(jié)束程序空镜。但仍要調(diào)用Thread.currentThread().interrupt()
恢復(fù)中斷浩淘,讓線程退出。
??
7吴攒、什么是線程安全张抄?
??線程安全就是多線程訪問(wèn)同一代碼,不會(huì)產(chǎn)生不確定的結(jié)果洼怔。
如何保證線程安全
對(duì)非安全的代碼進(jìn)行加鎖控制署惯;
使用線程安全的類;
多線程并發(fā)情況下镣隶,線程共享的變量改為方法級(jí)的局部變量极谊。
https://blog.csdn.net/suifeng3051/article/details/52164267
??
8诡右、synchronized 和 lock的區(qū)別
主要相同點(diǎn):
??Lock能完成synchronized所實(shí)現(xiàn)的所有功能
主要不同點(diǎn):
??Lock有比synchronized更精確的線程語(yǔ)義和更好的性能。
??Lock的鎖定是通過(guò)代碼實(shí)現(xiàn)的轻猖,而synchronized是在JVM層面上實(shí)現(xiàn)的帆吻,synchronized會(huì)自動(dòng)釋放鎖,而Lock一定要求程序員手工釋放咙边,并且必須在finally從句中釋放猜煮。
??Lock還有更強(qiáng)大的功能,例如败许,它的tryLock方法可以非阻塞方式去拿鎖王带。
??Lock鎖的范圍有局限性,塊范圍檐束,而synchronized可以鎖住塊辫秧、對(duì)象束倍、類被丧。
??
9、當(dāng)一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)synchronized方法后绪妹,其它線程是否可進(jìn)入此對(duì)象的其它方法?
現(xiàn)在分兩種情況來(lái)討論:
??1.當(dāng)前線程調(diào)用的是synchronized普通方法(相對(duì)于static方法)甥桂;
??2.當(dāng)前線程調(diào)用的是synchronized static方法。
1.當(dāng)前線程調(diào)用的是synchronized普通方法(相對(duì)于static方法)時(shí)邮旷,其它線程是否可進(jìn)入此對(duì)象的其它方法:
1)其它方法是加了synchronized的普通方法黄选,不能;
2)其它方法是沒(méi)加synchronized的普通方法婶肩,能办陷;
3)其它方法是synchronized的static方法,能律歼;
4)其它方法是沒(méi)加synchronized的static方法民镜,能。
5)如果這個(gè)方法內(nèi)部調(diào)用了wait险毁,則可以進(jìn)入其他synchronized方法制圈。
(因?yàn)楫?dāng)前線程執(zhí)行同步代碼塊或同步方法時(shí),程序執(zhí)行了同步監(jiān)視器對(duì)象的wait()方法畔况,則當(dāng)前線程暫停鲸鹦,并釋放同步器)
2.當(dāng)前線程調(diào)用的是synchronized static方法,其它線程是否可進(jìn)入此對(duì)象的其它方法:
1)其它方法是加了synchronized的普通方法跷跪,能馋嗜;
2)其它方法是沒(méi)加synchronized的普通方法,能吵瞻;
3)其它方法是synchronized的static方法嵌戈,不能覆积;
4)其它方法中有synchronized(xxx.class)的,不能熟呛;
5)其它方法是沒(méi)加synchronized的static方法宽档,能。
所謂的synchronized(xxx.class)就是同步代碼塊:
public void method5(){
synchronized(xxx.class){
System.out.println("this is a synchronized static method——method5.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
參考鏈接:java線程之——synchronized的注意細(xì)節(jié)
??
10庵朝、啟動(dòng)一個(gè)線程是用run()還是start()?
??啟動(dòng)一個(gè)線程是使用star()吗冤,啟動(dòng)線程后,系統(tǒng)會(huì)把該線程的run()方法當(dāng)成線程執(zhí)行體來(lái)處理九府。
??如果使用的是run()方法椎瘟,則run()方法會(huì)被立即執(zhí)行,而且在run()方法返回之前其他線程無(wú)法并發(fā)執(zhí)行侄旬。
??因此如果直接調(diào)用線程對(duì)象的run()方法肺蔚,系統(tǒng)會(huì)把線程對(duì)象當(dāng)成一個(gè)普通對(duì)象,而run()方法也是一個(gè)普通方法儡羔,而不是線程體宣羊。
??
11、wait和sleep的區(qū)別
??sleep()方法是Thread類中方法汰蜘,而wait()方法是Object類中的方法仇冯。
??sleep()方法導(dǎo)致了程序暫停執(zhí)行指定的時(shí)間,讓出cpu該其他線程族操,但是它的監(jiān)控狀態(tài)依然保持者苛坚,當(dāng)指定的時(shí)間到了又會(huì)自動(dòng)恢復(fù)運(yùn)行狀態(tài)。在調(diào)用sleep()方法的過(guò)程中色难,線程不會(huì)釋放對(duì)象鎖泼舱。
??而當(dāng)調(diào)用wait()方法的時(shí)候,線程會(huì)放棄對(duì)象鎖枷莉,進(jìn)入等待此對(duì)象的等待鎖定池娇昙,只有針對(duì)此對(duì)象調(diào)用notify()方法后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備。
??
12依沮、notify()和notifyAll()的區(qū)別
notify():
??喚醒在次同步監(jiān)視器上等待的單個(gè)線程涯贞,如果所有線程都在此同步監(jiān)視器上等待,則會(huì)選擇喚醒其中一個(gè)線程危喉。
??選擇是任意性的宋渔。只有當(dāng)前線程放棄對(duì)該同步監(jiān)視器的鎖定后(使用wait()方法),才可以執(zhí)行被喚醒的線程
notifyAll():
??喚醒在此同步監(jiān)視器上等待的所有線程辜限。只有當(dāng)前線程放棄該同步監(jiān)視器的鎖定后皇拣,才可以執(zhí)行被喚醒的線程。
??