Java并發(fā)編程

并發(fā)編程中的3個(gè)概念
1.原子性:操作中包含的步驟,要么都執(zhí)行成功,要么都失敗。
2.可見性:一個(gè)線程修改了變量的值朋魔,其他線程能夠立即看到修改的值。
3.有序性:JVM處理器在執(zhí)行指令時(shí)會(huì)重排序以優(yōu)化運(yùn)行效率卿操,但是會(huì)考慮數(shù)據(jù)依賴問題警检。但是如果多線程時(shí)重排序會(huì)造成程序執(zhí)行的正確性。所以多線程時(shí)要保證代碼執(zhí)行的有序性害淤。

原子性

例如:
x = 10; //語句1
y = x; //語句2
x++; //語句3
x = x + 1; //語句4
上面4個(gè)語句扇雕,哪些是原子性操作?
答:第一個(gè)是窥摄,其他的都不是洼裤。第一個(gè)x賦值為10,然后再同步到主存中溪王,是一個(gè)原子操作。
第二個(gè)首先要從主存中讀x的值值骇,然后再賦值給y莹菱,2個(gè)步驟各自是原子操作,但合在一起不是原子操作吱瘩。
同理x++,x=x+1,也不是原子操作道伟。

可以看出Java內(nèi)存模型中讀取、賦值操作為原子操作。那如何保證更大范圍的原子操作呢蜜徽?
那就使用到了synchronized和Lock祝懂,這兩個(gè)悲觀鎖可以保證同一時(shí)刻只有一個(gè)線程訪問被修飾的代碼,自然也就是原子操作了拘鞋。

可見性

經(jīng)過volatile修飾的共享變量砚蓬,可以將修改后的值立即更新到主存。如果普通共享變量盆色,值更新到主存的時(shí)機(jī)是不確定的灰蛙,所以沒有可見性。除此之外隔躲,synchronized和Lock在釋放鎖之前會(huì)更新主存摩梧,也能保證可見性。

有序性

Java內(nèi)存模型允許編譯器宣旱、處理器對(duì)指令重排序仅父,單線程無影響,多線程會(huì)影響浑吟,所以synchronized笙纤、Lock都能保證有序性。
添加volatile關(guān)鍵字修飾后买置,能夠保證一定的有序性粪糙,同時(shí)Java內(nèi)存模型先天有一些happens-before原則也可以保證有序性。
happens-before(先行發(fā)生行為)原則:
程序次序規(guī)則:一個(gè)線程內(nèi)忿项,按照書寫順序蓉冈,寫在前面的先執(zhí)行。事實(shí)上單線程程序指令依然會(huì)重排轩触,但是能夠保證結(jié)果的一致性寞酿。
鎖定規(guī)則:一個(gè)鎖必須釋放后,才能夠繼續(xù)加鎖脱柱。
volatile規(guī)則:寫操作發(fā)生在讀操作之前伐弹。一個(gè)線程寫,一個(gè)線程讀榨为,讀在寫后面惨好。
傳遞規(guī)則:A操作先于B操作,B操作先于C操作随闺,則A操作限于C操作日川。
線程啟動(dòng)規(guī)則:Thread的start()方法先行于線程內(nèi)的一切操作。
線程中斷規(guī)則:Thread的interrupt()方法先行于該線程代碼檢測(cè)到中斷事件的發(fā)生矩乐。
線程的終結(jié)規(guī)則:線程中所有的操作都先行于線程的終止檢測(cè)龄句。
對(duì)象的終結(jié)規(guī)則:一個(gè)對(duì)象的初始化方法先行于finalize()方法的開始回论。

相關(guān)題目

1.進(jìn)程和線程之間區(qū)別?
一個(gè)進(jìn)程是一個(gè)獨(dú)立的運(yùn)行環(huán)境,線程是進(jìn)程中的一個(gè)任務(wù)分歇,進(jìn)程中可以包含多個(gè)線程傀蓉,各個(gè)線程間可以共享進(jìn)程的資源。
2.多線程編程的好處职抡?
多線程用以提高程序的執(zhí)行效率葬燎,一些線程資源等待時(shí),cpu可以去處理其他線程繁调,減少了空閑狀態(tài)萨蚕。多個(gè)線程間還可以共享堆內(nèi)存,所以多線程程序比單線程程序更好蹄胰。
3.用戶線程和守護(hù)線程的區(qū)別岳遥?
默認(rèn)新建的thread是用戶線程,thread.setDaemon(true)可設(shè)置守護(hù)線程裕寨。平常處理邏輯的線程為用戶線程浩蓉,程序運(yùn)行時(shí)在后臺(tái)提供通用服務(wù)的線程設(shè)置為守護(hù)進(jìn)程(如jvm的垃圾回收線程)。守護(hù)線程創(chuàng)建的線程也是守護(hù)線程宾袜。
4.如何創(chuàng)建線程捻艳?
兩種方法:通過繼承Thread類或者實(shí)現(xiàn)Runable接口覆蓋或?qū)崿F(xiàn)其中的run()方法,然后再調(diào)用new thread再start()
5.線程的生命周期庆猫?
新建:當(dāng)new thread()時(shí)认轨,線程處理“新建”狀態(tài);
就緒&運(yùn)行:thread.start()之后月培,如何沒有分配cpu等資源為就緒嘁字,分配了cpu等資源為運(yùn)行狀態(tài);
阻塞:線程被掛起為阻塞狀態(tài)杉畜,如thread.join()纪蜒,thread.sleep(),等待用戶輸入等此叠,將線程放入到阻塞隊(duì)列中纯续,阻塞消除變?yōu)榫途w狀態(tài);
等待:當(dāng)前線程需要等待其他線程的一些特定動(dòng)作時(shí)(如某個(gè)對(duì)象被synchronized(o)加鎖灭袁;o.wait()時(shí)需要其他線程o.notify()猬错、o.notifyAll()喚醒);
超時(shí)等待:等待的基礎(chǔ)上茸歧,超時(shí)了兔魂;
終止:線程運(yùn)行完畢。

image.png

6.我們可以直接調(diào)用thread的run()方法嗎举娩?
可以的,直接調(diào)用和普通類就一樣了。如果要在一個(gè)線程中啟動(dòng)另一個(gè)線程的話铜涉,就需要thread.start()了
7.線程的優(yōu)先級(jí)智玻?
我們可以定義線程的優(yōu)先級(jí),1代表最低芙代,10代表最高吊奢,一般來說高優(yōu)先級(jí)線程會(huì)有具有優(yōu)先權(quán),但是它的實(shí)現(xiàn)是操作系統(tǒng)實(shí)現(xiàn)的纹烹,并不能一定保證高優(yōu)先級(jí)在低優(yōu)先級(jí)線程前執(zhí)行页滚。
8.什么是線程調(diào)度器Thread Schedule和時(shí)間分片time slicing?
線程調(diào)度器是一個(gè)操作系統(tǒng)服務(wù)铺呵,它負(fù)責(zé)為就緒態(tài)的線程分配CPU時(shí)間片裹驰,可以繼續(xù)線程優(yōu)先級(jí)或線程等待時(shí)間,盡量通過程序自己控制線程的調(diào)度片挂,而不是依賴于不同操作系統(tǒng)的默認(rèn)實(shí)現(xiàn)幻林。
9.什么是多線程中的上下文切換(context-switching)?
上下文切換時(shí)存儲(chǔ)和恢復(fù)CPU狀態(tài)的過程音念,它使得線程能夠從中斷點(diǎn)恢復(fù)執(zhí)行沪饺。
10.如何確保main()方法是程序最終結(jié)束的線程?
在main()方法中開啟別的線程時(shí)闷愤,使用別的線程對(duì)象.join()方法整葡,將其同步在main()線程里即可。
11.線程間如何通信讥脐?
線程間如果共享資源時(shí)遭居,可以采用object對(duì)象的wait(),notify(),notiyAll()等方法通過加鎖的方式進(jìn)行通信。
12.為什么Java中wait(),notify()t,notifyAll()方法被定義在Object類里攘烛?
因?yàn)镴ava并沒有可供所有對(duì)象使用的鎖魏滚、同步器,但是所有類都繼承Object類坟漱,這樣每個(gè)對(duì)象都擁有了鎖鼠次、監(jiān)視器可用。
13.為什么wait(),notify(),notifyAll()方法必須要在同步方法或者同步代碼塊中被調(diào)用芋齿?
因?yàn)閷?duì)象的這些方法要調(diào)用的話腥寇,該線程必須持有該對(duì)象的鎖,調(diào)用完方法后再釋放鎖以便讓其他線程可以得到這個(gè)鎖繼續(xù)操作觅捆,這樣就需要通過同步來實(shí)現(xiàn)赦役。
14.為什么thread的sleep和yield方法是靜態(tài)的?
這是一個(gè)調(diào)用對(duì)象的強(qiáng)制規(guī)范問題栅炒,因?yàn)閟leep和yield只能對(duì)運(yùn)行中的線程起作用掂摔,使用靜態(tài)讓這兩個(gè)方法只能強(qiáng)行獲取當(dāng)前線程對(duì)象并操作术羔,如果不指定靜態(tài)那么可以控制其他非運(yùn)行狀態(tài)的線程執(zhí)行該方法,顯然是不可以的乙漓。
15.如何確保線程安全级历?
這里線程安全指的是線程間共享資源時(shí)不會(huì)錯(cuò)亂。
1:通過synchronized來對(duì)對(duì)象加鎖實(shí)現(xiàn)線程安全叭披;
2:使用線程安全的集合如ConcurrentHashMap來存儲(chǔ)共享數(shù)據(jù)寥殖;
3:使用原子類如AtomicInteger存儲(chǔ)共享數(shù)據(jù);
4:使用鎖涩蜘;
5:使用volatile關(guān)鍵字修飾變量嚼贡,保證線程從堆內(nèi)存讀取數(shù)據(jù),而不是從線程cache讀取數(shù)據(jù)同诫。
16.volatile關(guān)鍵字的作用粤策?
volatile關(guān)鍵字用來修飾變量,被修飾的變量具有多線程下的可見性剩辟、有序性掐场、原子性(保證原子操作,原子操作的組合操作不能保證原子性)
17.同步塊和同步方法哪個(gè)更好贩猎?
同步塊往往對(duì)對(duì)象的鎖能精確到更細(xì)粒度熊户,所以使用同步塊較好。
18.如何創(chuàng)建守護(hù)線程吭服?
新建一個(gè)thread后嚷堡,thread.setDaemon(true)然后再調(diào)用thread.start()就可以了。
19.什么是ThreadLocal艇棕?
線程類中的普通全局變量蝌戒,在多線程的時(shí)候會(huì)有線程不安全的問題,可以使用TheadLocal變量沼琉,各個(gè)線程通過get()北苟、set()方法獲得各自線程的變量。
20.什么是Thread Group打瘪,為什么不建議使用它友鼻?
ThreadGroup這個(gè)類提供了關(guān)于線程組的信息,主要2個(gè)功能是獲取線程組中活躍線程列表闺骚、為線程設(shè)置線程外部異常處理(因?yàn)榫€程run()方法不能拋出異常彩扔,只能打日志)。Java1.5后可以通過setUncaughtExceptionHandler(UncaughtExceptionHandler eh) 來設(shè)置僻爽,ThreadGroup已經(jīng)過時(shí)虫碉,所以不建議使用。
21.什么是Thread Dump線程轉(zhuǎn)儲(chǔ)胸梆?
是一個(gè)JVM活動(dòng)線程的列表敦捧,可以用來分析系統(tǒng)瓶頸死鎖等须板,一般使用JDK自帶的jstack等工具來分析。
22.什么是死鎖DeadLock兢卵,如何分析和避免死鎖逼纸?
兩個(gè)以上的線程永遠(yuǎn)互相阻塞的情況叫做死鎖。
分析死鎖:通過分析Thread Dump查看阻塞的線程以及他們等待的資源济蝉,每個(gè)資源有id,可以根據(jù)資源的id查看哪些線程擁有了它的對(duì)象鎖菠发。
避免死鎖:避免嵌套鎖王滤,在需要的地方使用,避免無期限等待滓鸠。
23.什么是Java Timer類雁乡?
Java Timer類是一個(gè)工具類,可以安排一個(gè)線程在未來的某個(gè)時(shí)間點(diǎn)執(zhí)行糜俗,執(zhí)行一次或者周期執(zhí)行踱稍。TimerTask是一個(gè)實(shí)現(xiàn)了Runnable接口的抽象類,繼承它然后交給Timer對(duì)象安排即可悠抹。


package com.journaldev.threads;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MyTimerTask extends TimerTask {

    @Override
    public void run() {
        System.out.println("Timer task started at:"+new Date());
        completeTask();
        System.out.println("Timer task finished at:"+new Date());
    }

    private void completeTask() {
        try {
            //assuming it takes 20 secs to complete the task
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String args[]){
        TimerTask timerTask = new MyTimerTask();
        //running timer task as daemon thread
        Timer timer = new Timer(true);
        timer.scheduleAtFixedRate(timerTask, 0, 10*1000);
        System.out.println("TimerTask started");
        //cancel after sometime
        try {
            Thread.sleep(120000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        timer.cancel();
        System.out.println("TimerTask cancelled");
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

24.什么是線程池珠月?
線程池用于管理多個(gè)工作線程。Executors是線程池的工廠類可以方便的創(chuàng)建線程池對(duì)象楔敌。

1. newCachedThreadPool 創(chuàng)建一個(gè)可緩存線程池啤挎,如果線程池長(zhǎng)度超過處理需要,可靈活回收空閑線程卵凑,若無可回收庆聘,則新建線程。
2. newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池勺卢,可控制線程最大并發(fā)數(shù)伙判,超出的線程會(huì)在隊(duì)列中等待。
3. newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池黑忱,支持定時(shí)及周期性任務(wù)執(zhí)行宴抚。
4. newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來執(zhí)行任務(wù)杨何,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行酱塔。

25.
26.危虱?
27.羊娃?
28.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末埃跷,一起剝皮案震驚了整個(gè)濱河市蕊玷,隨后出現(xiàn)的幾起案子邮利,更是在濱河造成了極大的恐慌,老刑警劉巖垃帅,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件延届,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贸诚,警方通過查閱死者的電腦和手機(jī)方庭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酱固,“玉大人械念,你說我怎么就攤上這事≡吮” “怎么了龄减?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)班眯。 經(jīng)常有香客問我希停,道長(zhǎng),這世上最難降的妖魔是什么署隘? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任宠能,我火速辦了婚禮,結(jié)果婚禮上定踱,老公的妹妹穿的比我還像新娘棍潘。我一直安慰自己,他們只是感情好崖媚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布亦歉。 她就那樣靜靜地躺著,像睡著了一般畅哑。 火紅的嫁衣襯著肌膚如雪肴楷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天荠呐,我揣著相機(jī)與錄音赛蔫,去河邊找鬼。 笑死泥张,一個(gè)胖子當(dāng)著我的面吹牛呵恢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播媚创,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼渗钉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鳄橘,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤声离,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后瘫怜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體术徊,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年鲸湃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赠涮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡暗挑,死狀恐怖世囊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窿祥,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布蝙寨,位于F島的核電站晒衩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏墙歪。R本人自食惡果不足惜听系,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虹菲。 院中可真熱鬧靠胜,春花似錦、人聲如沸毕源。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霎褐。三九已至址愿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冻璃,已是汗流浹背响谓。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留省艳,地道東北人娘纷。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像跋炕,于是被迫代替她去往敵國(guó)和親赖晶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354