国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

java多線(xiàn)程學(xué)習(xí)總結(jié)(一)

2019-11-11 07:52:11
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

java線(xiàn)程

應(yīng)用多線(xiàn)程一來(lái)可以為主線(xiàn)程分擔(dān)耗時(shí)較多的任務(wù),提高主線(xiàn)程的響應(yīng)速度,二來(lái)隨著計(jì)算機(jī)多處理能力的增加,可以提高計(jì)算機(jī)的使用性能。

首先我們來(lái)看java是如何創(chuàng)建線(xiàn)程的。創(chuàng)建一個(gè)線(xiàn)程傳統(tǒng)上有兩種方式,一種是繼承線(xiàn)程Thread類(lèi),創(chuàng)建Thread類(lèi)實(shí)例,調(diào)用start()方法;還有一種就是實(shí)現(xiàn)runnable接口,創(chuàng)建new Thread(runnable()).start().兩種方式本質(zhì)上還有創(chuàng)建一個(gè)線(xiàn)程類(lèi)。還可以采用executer.execute()的方式提交一個(gè)線(xiàn)程,或者更高級(jí)的executorService.submit()方法來(lái)提交線(xiàn)程。

當(dāng)多個(gè)線(xiàn)程同時(shí)運(yùn)行的時(shí)候,由于它們之間對(duì)于進(jìn)程的資源是共享的,對(duì)于共享的資源占有會(huì)有先后,因而會(huì)產(chǎn)生競(jìng)爭(zhēng)關(guān)系,同時(shí)還會(huì)產(chǎn)生資源的一致性問(wèn)題。這些關(guān)系綜合在一起會(huì)產(chǎn)生如果處理不當(dāng)會(huì)產(chǎn)生不良的后果。當(dāng)線(xiàn)程多的時(shí)候,多個(gè)線(xiàn)程之間的關(guān)系會(huì)有多種,一種是主子線(xiàn)程關(guān)系,即子線(xiàn)程為主線(xiàn)程服務(wù),協(xié)助主線(xiàn)程完成一個(gè)任務(wù),還有是并列關(guān)系,即為了提高程序響應(yīng)速度,采用多個(gè)線(xiàn)程來(lái)并發(fā)處理同樣的任務(wù),還有一種是順序/互補(bǔ)關(guān)系

1.主子關(guān)系

主子關(guān)系更多的是主線(xiàn)程將一個(gè)耗時(shí)較多的任務(wù)分給子線(xiàn)程,子線(xiàn)程處理完成后通知給主線(xiàn)程。這種關(guān)系通常不會(huì)產(chǎn)生對(duì)資源的同步訪(fǎng)問(wèn),但是會(huì)存在子線(xiàn)程處理完任務(wù)后通知主線(xiàn)程的問(wèn)題。那么如何解決這個(gè)問(wèn)題呢?其實(shí),java中一個(gè)線(xiàn)程在執(zhí)行完成任務(wù)后就會(huì)消亡,所以不會(huì)存在子線(xiàn)程主動(dòng)通知主線(xiàn)程,那么子線(xiàn)程如何通知主線(xiàn)程呢?這里有兩種方式,一種是設(shè)置共享變量,子線(xiàn)程完成后,更改共享變量的值來(lái)達(dá)到通知主線(xiàn)程其任務(wù)完成的目的,另外一種就是主線(xiàn)程在空閑的時(shí)候主動(dòng)探查子線(xiàn)程是否執(zhí)行完成任務(wù),一種方式是查看子線(xiàn)程是否還活動(dòng)(alive)t.isAlive(),如果還活動(dòng),那么可以選擇等待(t.join()),也可以繼續(xù)執(zhí)行它自己的任務(wù)。或者如果采用executorService.submit()方法來(lái)提交線(xiàn)程的話(huà),會(huì)得到一個(gè)furture對(duì)象,用于檢測(cè)子線(xiàn)程是否完成(furture.isDone)。

2. 并列關(guān)系

并列關(guān)系是比較復(fù)雜的多線(xiàn)程之間的關(guān)系,因?yàn)闀?huì)設(shè)計(jì)到多個(gè)線(xiàn)程對(duì)同一個(gè)共享資源的訪(fǎng)問(wèn),為了保證多個(gè)線(xiàn)程對(duì)同一個(gè)共享資源訪(fǎng)問(wèn)不出現(xiàn)沖突,java設(shè)計(jì)了一整套的方法來(lái)保證。

2.1 原子操作

首先,如果多個(gè)線(xiàn)程對(duì)于一個(gè)資源的訪(fǎng)問(wèn)過(guò)程都是一次性操作,而不存在操作過(guò)程中資源的中間狀態(tài),那么這樣的操作稱(chēng)為原子操作,如果線(xiàn)程對(duì)于資源的操作都是原子操作,那么多個(gè)線(xiàn)程之間就不需要同步,因?yàn)槠浔旧聿⒉淮嬖跊_突,那么對(duì)哪些資源的操作是原子操作呢?java中對(duì)于基本類(lèi)型以及對(duì)象的引用類(lèi)型,以及被聲明為volatile的變量

2.2 操作同步

那么如果對(duì)于一個(gè)資源的訪(fǎng)問(wèn)不是原子操作,而是帶有中間狀態(tài)的操作會(huì)怎樣呢?單以簡(jiǎn)單的c++為例,不考慮虛擬機(jī)的操作,c++可以分解為一下3步:

1)獲取c的值

2)將獲取的值加1;

3)將新的值寫(xiě)回到c

這樣的3步操作如果有多個(gè)線(xiàn)程同時(shí)進(jìn)行,那么后果就不是我們能夠預(yù)料的了。那么如何保證其操作的安全有序呢?java給出的解決方案是采用加鎖的方式來(lái)產(chǎn)生排他性操作,即我要訪(fǎng)問(wèn)某個(gè)資源,如果已經(jīng)被我占有了,那么我就會(huì)給它加上一把鎖,這樣,在我占有使用的過(guò)程中,讓其他線(xiàn)程無(wú)法使用,只有我用完了,把鎖釋放了后其他線(xiàn)程才能使用。那么如何加鎖呢?最普遍常見(jiàn)的方法是在方法上使用synchronized關(guān)鍵字。加上synchronized關(guān)鍵字的方法是在一個(gè)線(xiàn)程執(zhí)行過(guò)程中會(huì)對(duì)其他線(xiàn)程產(chǎn)生排他性操作。那么synchronized關(guān)鍵字是否給方法上了鎖呢?答案是是的,這里涉及到內(nèi)在鎖的概念,在java中,每一個(gè)對(duì)象都有一個(gè)內(nèi)在鎖與它關(guān)聯(lián),一個(gè)線(xiàn)程要想排他性的訪(fǎng)問(wèn)一個(gè)對(duì)象的字段必須首先獲得對(duì)象的內(nèi)部鎖,一旦獲得了該對(duì)象的內(nèi)部鎖,在其釋放之前,其他線(xiàn)程是無(wú)法獲取到該鎖的。那么這個(gè)內(nèi)部鎖到底是什么呢,我們可以理解為其就是對(duì)象本身,所以我們只要鎖定對(duì)象本身,我們就獲得了對(duì)象的訪(fǎng)問(wèn)權(quán),所以我們還可以顯式的去鎖定對(duì)象synchronized(this),這樣我們就可以更靈活的不去鎖定這個(gè)方法本身,而是鎖定方法中需要同步的某個(gè)代碼塊。進(jìn)而我們還可以顯式的定義與每個(gè)字段關(guān)聯(lián)的對(duì)象鎖,方便對(duì)每個(gè)字段的排他性訪(fǎng)問(wèn)而互不影響。

public class MsLunch {    

PRivate long c1 = 0;    

private long c2 = 0;    

private Object lock1 = new Object();    

private Object lock2 = new Object();     

public void inc1() {       

synchronized(lock1) {         

  c1++;        

}    

}     

public void inc2() {   

    synchronized(lock2) {    

        c2++;       

}    

}

}

2.3 鎖

鎖單獨(dú)講,其所應(yīng)有的含義應(yīng)該是能加鎖和釋放鎖。java.util.concurrent.locks中的lock接口就給出了這樣的解釋。它本身包含lock()和unlock()方法。這樣,我們就可以在需要加鎖的地方顯式的進(jìn)行加鎖,lock.lock(),用完之后顯式的釋放掉鎖lock.unlock(),java.util.concurrent.locks中給我們提供了兩種常用的鎖的實(shí)現(xiàn)。

2.3.1 重入鎖ReentrantLock

重入鎖是在線(xiàn)程可以再次獲取到它已經(jīng)擁有的鎖,即對(duì)對(duì)象進(jìn)行二次加鎖。對(duì)象的內(nèi)部鎖也是支持重入的。

2.3.2 重入讀寫(xiě)鎖ReentrantReadWriteLock重入讀寫(xiě)鎖是對(duì)一個(gè)資源既存在讀操作又存在寫(xiě)操作的情況下定義的鎖,該鎖實(shí)際上包含兩把鎖,讀鎖和寫(xiě)鎖。讀鎖對(duì)其他的讀操作沒(méi)有排他性,但是寫(xiě)鎖對(duì)于其他操作有排他性,也就是說(shuō)當(dāng)獲取讀鎖的時(shí)候只要該資源沒(méi)有寫(xiě)鎖就可以,但是當(dāng)獲取寫(xiě)鎖的時(shí)候必須要當(dāng)前資源沒(méi)有鎖,否則該線(xiàn)程將會(huì)處于等待過(guò)程中。很顯然,讀寫(xiě)鎖對(duì)于資源處于大多數(shù)讀操作少量寫(xiě)操作的時(shí)候有很大的優(yōu)勢(shì),反之,會(huì)降低程序的性能。

3.互補(bǔ)關(guān)系

當(dāng)兩個(gè)線(xiàn)程之間的執(zhí)行是后一個(gè)線(xiàn)程需要前一個(gè)線(xiàn)程為其提供條件,而后一個(gè)線(xiàn)程的執(zhí)行又為前一個(gè)線(xiàn)程的執(zhí)行提供保障,我稱(chēng)之為互補(bǔ)關(guān)系,典型的例子是生產(chǎn)-消費(fèi)者模型。消費(fèi)者需要生產(chǎn)者為其提供產(chǎn)品,消費(fèi)者同樣需要消費(fèi)產(chǎn)品為生產(chǎn)者提供空間。這樣的兩個(gè)線(xiàn)程之間,雖然也存在對(duì)共同資源的訪(fǎng)問(wèn)-產(chǎn)品存放空間,這個(gè)通過(guò)前述各種同步就能夠很好地解決,但是還有一個(gè)新的問(wèn)題,就是當(dāng)生產(chǎn)者有了產(chǎn)品的時(shí)候如何通知消費(fèi)者,同樣消費(fèi)者消耗掉產(chǎn)品如何通知生產(chǎn)者繼續(xù)生產(chǎn),如果通過(guò)前述的方式,二者設(shè)置共享變量,那么就會(huì)存在生產(chǎn)者和消費(fèi)者不斷地對(duì)變量進(jìn)行輪詢(xún)(Guarded Blocks),從而消耗大量cpu資源,又二者不屬于主從關(guān)系,因此無(wú)法使用join,那么解決這個(gè)問(wèn)題就引入了新的機(jī)制,等待-通知機(jī)制(wait-notify/notifyAll)。當(dāng)生產(chǎn)者發(fā)現(xiàn)生產(chǎn)空間已經(jīng)占滿(mǎn),就處于等待狀態(tài)wait,程序?qū)⑸a(chǎn)者線(xiàn)程掛起,當(dāng)消費(fèi)者取走產(chǎn)品釋放出空間的時(shí)候,就通知notify生產(chǎn)者去生產(chǎn)產(chǎn)品,同樣當(dāng)消費(fèi)者發(fā)現(xiàn)沒(méi)有產(chǎn)品的時(shí)候,也處于等待狀態(tài)(wait),生產(chǎn)者將產(chǎn)品生產(chǎn)好以后,就通知(notify)消費(fèi)者。采用顯式加鎖的方案是對(duì)鎖對(duì)象產(chǎn)生條件性(condition)等待,當(dāng)對(duì)生產(chǎn)空間進(jìn)行加鎖lock后,生產(chǎn)者對(duì)于生產(chǎn)空間添加產(chǎn)品,發(fā)出非空信號(hào)(notEmpty.signal()),同時(shí)產(chǎn)生非滿(mǎn)(notFull=lock.newCondition())等待(notFull.await()),消費(fèi)者對(duì)于生產(chǎn)空間產(chǎn)生非空(notEmpty=lock.newCondition())等待(notEmpty.await()),當(dāng)被喚醒后取走產(chǎn)品發(fā)出(notFull.signal())喚醒生產(chǎn)者。  


上一篇:JAVA枚舉類(lèi)

下一篇:Java NIO 教程

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 美姑县| 永安市| 镇巴县| 于都县| 临潭县| 抚松县| 广东省| 拉萨市| 龙江县| 靖宇县| 英吉沙县| 浑源县| 西青区| 青海省| 陆河县| 太仓市| 阳高县| 青龙| 尼玛县| 平度市| 同仁县| 四会市| 秦安县| 安阳市| 卓尼县| 麻栗坡县| 新源县| 启东市| 阳曲县| 建湖县| 佳木斯市| 长乐市| 康平县| 图们市| 康保县| 碌曲县| 交城县| 安多县| 石景山区| 河源市| 永寿县|