成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

java并發(fā)編程學(xué)習(xí)1--基礎(chǔ)知識(shí)

huangjinnan / 1082人閱讀

摘要:死亡狀態(tài)線程退出有可能是正常執(zhí)行完成也有可能遇見異常退出。類有新建與死亡狀態(tài)返回其余狀態(tài)返回判斷線程是否存活。線程因某些原因進(jìn)入阻塞狀態(tài)。執(zhí)行同步代碼塊的過程中執(zhí)行了當(dāng)前線程放棄開始睡眠進(jìn)入就緒狀態(tài)但是不會(huì)釋放鎖。

【java內(nèi)存模型簡(jiǎn)介

JVM中存在一個(gè)主存區(qū)(Main Memory或Java Heap Memory),Java中所有變量都是存在主存中的,對(duì)于所有線程進(jìn)行共享,而每個(gè)線程又存在自己的工作內(nèi)存(Working Memory),工作內(nèi)存中保存的是主存中某些變量的拷貝,線程對(duì)所有變量的操作并非發(fā)生在主存區(qū),而是發(fā)生在工作內(nèi)存中,而線程之間是不能直接相互訪問,變量在程序中的傳遞,是依賴主存來完成的。而在多核處理器下,大部分?jǐn)?shù)據(jù)存儲(chǔ)在高速緩存中,如果高速緩存不經(jīng)過內(nèi)存的時(shí)候,也是不可見的一種表現(xiàn)。在Java程序中,內(nèi)存本身是比較昂貴的資源,其實(shí)不僅僅針對(duì)Java應(yīng)用程序,對(duì)操作系統(tǒng)本身而言內(nèi)存也屬于昂貴資源,Java程序在性能開銷過程中有幾個(gè)比較典型的可控制的來源。synchronized和volatile關(guān)鍵字提供的內(nèi)存中模型的可見性保證程序使用一個(gè)特殊的、存儲(chǔ)關(guān)卡(memory barrier)的指令,來刷新緩存,使緩存無效,刷新硬件的寫緩存并且延遲執(zhí)行的傳遞過程,無疑該機(jī)制會(huì)對(duì)Java程序的性能產(chǎn)生一定的影響。

【java線程的運(yùn)行機(jī)制

在java虛擬機(jī)進(jìn)程中,執(zhí)行程序代碼的任務(wù)是由線程看來完成的。每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器和方法調(diào)用棧。程序計(jì)數(shù)器:pc寄存器,當(dāng)線程執(zhí)行一個(gè)方法時(shí),程序計(jì)數(shù)器指向方法區(qū)中下一條要執(zhí)行的字節(jié)碼指令。方法調(diào)用棧:用來跟蹤線程運(yùn)行中一系列方法的調(diào)用過程,棧中的元素稱為棧幀。每當(dāng)線程調(diào)用一個(gè)方法,就會(huì)壓棧一個(gè)新幀,幀用來保存方法的參數(shù),局部變量,運(yùn)算過程中產(chǎn)生的臨時(shí)數(shù)據(jù)。java虛擬機(jī)的主線程是它從啟動(dòng)類的main()方法開始運(yùn)行。此外,用戶也可以創(chuàng)建自己的線程,兩種方式:繼承 Thread 類,實(shí)現(xiàn) Runnable 接口。
但是運(yùn)行一個(gè)線程必須使用Thread.strat(),切記:1.不可直接運(yùn)行run(),直接運(yùn)行run()只是單純的方法調(diào)用,并不會(huì)產(chǎn)出新的線程。2.不要隨意覆蓋start(),如果必須覆蓋記得首先調(diào)用super.start()。線程是不會(huì)順序執(zhí)行的,一切都由操作系統(tǒng)調(diào)度決定,并且一個(gè)線程只能啟動(dòng)一次,第二次啟動(dòng)會(huì)拋出:IllegalThreadStateException,但是并不會(huì)影響之前啟動(dòng)的線程工作。

public class MyRunnable implements Runnable{
            @Override
            public void run() {
                    System.out.println("runnable running");
           }
    }

    
    public class MyThread extends Thread{
            @Override
             public void run(){
                System.out.println("thread running");
            }
    }
【java線程狀態(tài)

新建狀態(tài):new 語句創(chuàng)建的狀態(tài),此時(shí)它和其他java對(duì)象一樣,僅僅在堆中被分配了內(nèi)存。

就緒狀態(tài):當(dāng)一個(gè)線程被其他線程調(diào)用了start(),此時(shí)jvm會(huì)為它創(chuàng)建程序計(jì)數(shù)器和方法調(diào)用棧。處于改狀態(tài)的線程位于可運(yùn)行池,等待獲取CPU的執(zhí)行權(quán)。

運(yùn)行狀態(tài):處于改狀態(tài)的線程占用CPU,正在執(zhí)行程序代碼。如果計(jì)算機(jī)只有一個(gè)單核CPU那么永遠(yuǎn)hi只有一個(gè)線程處于改狀態(tài)。只有處于就緒狀態(tài)的線程才可能成為運(yùn)行狀態(tài)。

阻塞狀態(tài):線程因?yàn)槟承┰蚍艞壛薈PU暫停執(zhí)行。此時(shí)線程放棄CPU的執(zhí)行權(quán),直到進(jìn)入就緒狀態(tài)才可能再次變?yōu)檫\(yùn)行狀態(tài)。阻塞狀態(tài)3中情況:

對(duì)象等待池阻塞:線程執(zhí)行了某個(gè)對(duì)象的wait(),線程被jvm放入這個(gè)對(duì)象的等待池之中。(用sleep()方法的過程中,線程不會(huì)釋放對(duì)象鎖。而當(dāng)調(diào)用wait()方法的時(shí)候,線程會(huì)放棄對(duì)象鎖,進(jìn)入等待此對(duì)象的等待鎖定池,只有針對(duì)此對(duì)象調(diào)用notify()方法后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備。)

對(duì)象同步鎖阻塞:線程試圖獲取對(duì)象的同步鎖,如果同步鎖已經(jīng)被其他線程持有,jvm會(huì)把該線程放入對(duì)象鎖池中。

其他阻塞狀態(tài):當(dāng)前線程執(zhí)行sleep(),或者調(diào)用其它線程的join()(把指定的線程加入到當(dāng)前線程,可以將兩個(gè)交替執(zhí)行的線程合并為順序執(zhí)行的線程。比如在線程B中調(diào)用了線程A的Join()方法,直到線程A執(zhí)行完畢后,才會(huì)繼續(xù)執(zhí)行線程B。),或者發(fā)出了IO請(qǐng)求。

死亡狀態(tài):線程退出run(),有可能是正常執(zhí)行完成,也有可能遇見異常退出。但是都不會(huì)對(duì)其他線程造成影響。Thread類有isAlive()(新建與死亡狀態(tài)返回false,其余狀態(tài)返回true)判斷線程是否存活。

【線程調(diào)度

一個(gè)單核CPU在一個(gè)時(shí)刻只能執(zhí)行一個(gè)機(jī)器指令。線程只有通過獲得CPU才能執(zhí)行自己的程序代碼。所謂多線程的并發(fā)執(zhí)行,其實(shí)從宏觀上來看:各個(gè)線程輪流獲得CPU的使用權(quán),分別執(zhí)行各自的任務(wù)。jvm采用搶占式調(diào)度模型,是指先讓高優(yōu)先級(jí)線程獲得CPU。如果優(yōu)先級(jí)相同,隨機(jī)選擇一個(gè)執(zhí)行。處于運(yùn)行狀態(tài)的線程或一直執(zhí)行,直到不得不放棄CPU,一般有如下原因:

1. jvm讓其放棄CPU轉(zhuǎn)入就緒狀態(tài)。        
2. 線程因某些原因進(jìn)入阻塞狀態(tài)。       
3. 運(yùn)行結(jié)束退出run()。

值得注意一點(diǎn):java的線程優(yōu)先級(jí)使用Thread.setPriority(int)設(shè)置,通常三個(gè)靜態(tài)常量選擇:Thread.MAX_PRIORITY(默認(rèn):10),Thread.MIN_PRIORITY(默認(rèn):1),Thread.NORM_PRIORITY(默認(rèn):5)。但是各個(gè)操作系統(tǒng)的線程優(yōu)先級(jí)并不相同,所以為了確保程序能夠在不同平臺(tái)正常執(zhí)行,我們只是用這三個(gè)值,不會(huì)使用1-10中的其他數(shù)字。常用方法:

Thread.sleep(long millis): 當(dāng)前線程放棄CPU進(jìn)入阻塞狀態(tài),經(jīng)過milli毫秒后恢復(fù)就緒狀態(tài),不放棄對(duì)象鎖的持有。

Thread.yield(): 讓出CPU執(zhí)行權(quán)進(jìn)入就緒狀態(tài),給另一個(gè)擁有相同或者大于優(yōu)先級(jí)的線程,如果沒滿足條件的線程,則什么都不做。

Thread.join(): 當(dāng)前線程調(diào)用另一個(gè)線程的join(),并且等待被調(diào)用線程執(zhí)行完后再繼續(xù)執(zhí)行。

Object.wait(): 當(dāng)前線程必須擁有當(dāng)前對(duì)象鎖。如果當(dāng)前線程不是此鎖的擁有者,會(huì)拋出IllegalMonitorStateException異常。喚醒當(dāng)前對(duì)象鎖的等待線程使用notify或notifyAll方法,也必須擁有相同的對(duì)象鎖,否則也會(huì)拋出IllegalMonitorStateException異常。waite()和notify()必須synchronized函數(shù)或synchronized block中進(jìn)行調(diào)用。如果在non-synchronized函數(shù)或non-synchronized block中進(jìn)行調(diào)用,雖然能編譯通過,但在運(yùn)行時(shí)會(huì)發(fā)生IllegalMonitorStateException的異常。

Object.notify(): 執(zhí)行該方法的線程隨機(jī)喚醒對(duì)象等待池中的一個(gè)線程,并將其裝入對(duì)象鎖池之中。

【線程的同步與并發(fā)

并發(fā)編程三個(gè)概念:

原子性:一個(gè)操作或者多個(gè)操作,要么全部成功,要么全部失敗。

可見性:當(dāng)多個(gè)線程訪問同一變量時(shí),一個(gè)線程修改了該變量的值,其他線程能立即看到修改后的值。

有序性:程序執(zhí)行的順序按照代碼的先后順序執(zhí)行。(你以為這是廢話?請(qǐng)了解指令重排序)。這三個(gè)特性中2,3可以由volatile關(guān)鍵字保證(2.緩存一致性協(xié)議,3.禁止指令重排序),1只能由同步方式保證。

同步是解決資源共享的有效手段。當(dāng)一個(gè)線程在操作共享變量的時(shí)候,其他線程只能等待。只有當(dāng)該線程執(zhí)行完同步代碼塊后,其他線程才能有機(jī)會(huì)操作共享資源。通常有如下幾種同步方式:

synchorized關(guān)鍵字: 修飾方法或者使用同步代碼塊。

ReentrantLock重入鎖對(duì)象: 鎖住共享變量的操作。

使用并發(fā)數(shù)據(jù)結(jié)構(gòu)對(duì)象:Atomic系列,Concurrent系列等。

但是同步的操作,代價(jià)較大,我們應(yīng)該盡可能減少同步操作,是的一個(gè)線程能盡快的釋放鎖,減少其他線程執(zhí)行的時(shí)間。由于等待一個(gè)鎖的線程只有在獲得了這把鎖之后,
才能繼續(xù)執(zhí)行所以讓持有鎖的線程及時(shí)釋放鎖的相當(dāng)重要的。

以下情況線程釋放鎖:

執(zhí)行完同步代碼塊。

執(zhí)行同步代碼塊的過程中,遇見異常,線程死亡,鎖被釋放。

執(zhí)行同步代碼塊的過程中,執(zhí)行了鎖所屬對(duì)象的wait(),這個(gè)線程會(huì)釋放鎖進(jìn)入對(duì)象等待池。

以下情況線程不會(huì)釋放鎖:

執(zhí)行同步代碼塊的過程中,執(zhí)行了Thread.sleep(),當(dāng)前線程放棄CPU開始睡眠進(jìn)入阻塞狀態(tài),但是不會(huì)釋放鎖。

執(zhí)行同步代碼塊的過程中,執(zhí)行了Thread.yield(),當(dāng)前線程放棄CPU開始睡眠進(jìn)入就緒狀態(tài),但是不會(huì)釋放鎖。

執(zhí)行同步代碼塊的過程中,其他線程執(zhí)行了當(dāng)前線程的suspend()(已廢棄,同時(shí)廢棄的還有:Thread.stop(),Thread.resume()),當(dāng)前線程被暫停,但是不會(huì)釋放鎖。 死鎖兩個(gè)線程互相等待對(duì)方持有的鎖,統(tǒng)統(tǒng)進(jìn)入阻塞狀態(tài),jvm不檢測(cè)也不避免這種情況。

【線程通信

不同的線程需要協(xié)作完成工作(一種情況是:線程2需要線程1的執(zhí)行結(jié)果)。

- Object.wait(): 執(zhí)行該放大的線程釋放它持有的該對(duì)象的共享鎖(前提時(shí)必須持有該共享鎖),該線程進(jìn)入對(duì)象等待池,等待其他線程將其喚醒。
    
- Object.notify(): 執(zhí)行該方法的線程隨機(jī)喚醒對(duì)象等待池中的一個(gè)線程,并將其裝入對(duì)象鎖池之中。

補(bǔ)充:

1.鎖池:假設(shè)線程A已經(jīng)擁有了某個(gè)對(duì)象(注意:不是類)的鎖,而其它的線程想要調(diào)用這個(gè)對(duì)象的某個(gè)synchronized方法(或者synchronized塊),由于這些線程在進(jìn)入對(duì)象的synchronized方法之前必須先獲得該對(duì)象的鎖的擁有權(quán)。但是該對(duì)象的鎖目前正被線程A擁有,所以這些線程就進(jìn)入了該對(duì)象的鎖池中。

2.等待池:假設(shè)一個(gè)線程A調(diào)用了某個(gè)對(duì)象的wait()方法,線程A就會(huì)釋放該對(duì)象的鎖(因?yàn)閣ait()方法必須出現(xiàn)在synchronized中,這樣自然在執(zhí)行wait()方法之前線程A就已經(jīng)擁有了該對(duì)象的鎖),同時(shí)線程A就進(jìn)入到了該對(duì)象的等待池中。如果另外的一個(gè)線程調(diào)用了相同對(duì)象的notifyAll()方法,那么處于該對(duì)象的等待池中的線程就會(huì)全部進(jìn)入該對(duì)象的鎖池中,準(zhǔn)備爭(zhēng)奪鎖的擁有權(quán)。如果另外的一個(gè)線程調(diào)用了相同對(duì)象的notify()方法,那么僅僅有一個(gè)處于該對(duì)象的等待池中的線程(隨機(jī))會(huì)進(jìn)入該對(duì)象的鎖池。步驟如下(后面會(huì)有代碼實(shí)例):

   1. t1執(zhí)行s的一個(gè)同步代碼塊,t1持有s的共享鎖,t2在s的鎖池中等待。
   
   2. t1在同步代碼中執(zhí)行s.wait(0,t1釋放s的共享鎖,進(jìn)入s的等待池。
   
   3. s的鎖池中t2獲得共享鎖執(zhí)行s的另一同步代碼塊。
   
   4. t2在同步代碼塊中執(zhí)行s.notify(),JVM將t1從s的等待池轉(zhuǎn)入s的鎖池。
   
   5. t2完成同步代碼,釋放鎖,t1獲得鎖繼續(xù)執(zhí)行同步代碼。        
    

eg:兩個(gè)線程,一個(gè)線程將某個(gè)對(duì)象的某個(gè)成員變量的值加1,而另外一個(gè)線程將這個(gè)成員變量的值減1.使得該變量的值始終處于[0,2].初始值為0:

【中斷阻塞

當(dāng)一個(gè)線程處于阻塞狀態(tài)時(shí),另一個(gè)線程調(diào)用阻塞線程的interrupt(),阻塞線程收到InterruptException,并退出阻塞狀態(tài),開始進(jìn)行異常處理。代碼:

@Override            
        public void run() {                
            System.out.println("runnable running");                
            try {                   
                 Thread.sleep(1l);                
            } catch (InterruptedException e) {     
                  //-----start異常處理----                    
                e.printStackTrace();                   
                  //-----end異常處理-----                
            }            
        }
【總結(jié)

并發(fā)編程的知識(shí)非常復(fù)雜,以上只是一些皮毛,后續(xù)還將學(xué)習(xí)Synchronized,ReentrantLock,F(xiàn)uture,F(xiàn)utureTask,Executor,F(xiàn)ork/Join,CompletableFuture,Map-Reduce等相關(guān)知識(shí),最后用一個(gè)實(shí)際項(xiàng)目來完成這部分知識(shí)的學(xué)習(xí)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68063.html

相關(guān)文章

  • Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問題

    摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。很多編程語言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時(shí)至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...

    dingding199389 評(píng)論0 收藏0
  • 學(xué)習(xí)Java必讀的10本書籍

    摘要:學(xué)習(xí)編程的本最佳書籍這些書涵蓋了各個(gè)領(lǐng)域,包括核心基礎(chǔ)知識(shí),集合框架,多線程和并發(fā),內(nèi)部和性能調(diào)優(yōu),設(shè)計(jì)模式等。擅長(zhǎng)解釋錯(cuò)誤及錯(cuò)誤的原因以及如何解決簡(jiǎn)而言之,這是學(xué)習(xí)中并發(fā)和多線程的最佳書籍之一。 showImg(https://segmentfault.com/img/remote/1460000018913016); 來源 | 愿碼(ChainDesk.CN)內(nèi)容編輯 愿碼Slo...

    masturbator 評(píng)論0 收藏0
  • java并發(fā)編程學(xué)習(xí)---之一

    摘要:開始學(xué)習(xí)也有一段時(shí)間了,一些基礎(chǔ)的書也掃了一遍了。最近慢慢開始看和,后者的話和有類似之處,都是一些編程經(jīng)驗(yàn)的編程的世界里好多的東西都是相同的。這里其實(shí)是對(duì)的最佳實(shí)踐,之后該對(duì)象已經(jīng)變成一個(gè)過期的引用了,此時(shí)就應(yīng)該清空這個(gè)引用。 開始學(xué)習(xí)java也有一段時(shí)間了,一些基礎(chǔ)的書也掃了一遍了(think in java/core java volume 1)。最近慢慢開始看和,后者的話和有類似...

    chavesgu 評(píng)論0 收藏0
  • Java學(xué)習(xí)必備書籍推薦終極版!

    摘要:實(shí)戰(zhàn)高并發(fā)程序設(shè)計(jì)推薦豆瓣評(píng)分書的質(zhì)量沒的說,推薦大家好好看一下。推薦,豆瓣評(píng)分,人評(píng)價(jià)本書介紹了在編程中條極具實(shí)用價(jià)值的經(jīng)驗(yàn)規(guī)則,這些經(jīng)驗(yàn)規(guī)則涵蓋了大多數(shù)開發(fā)人員每天所面臨的問題的解決方案。 很早就想把JavaGuide的書單更新一下了,昨晚加今天早上花了幾個(gè)時(shí)間對(duì)之前的書單進(jìn)行了分類和補(bǔ)充完善。雖是終極版,但一定還有很多不錯(cuò)的 Java 書籍我沒有添加進(jìn)去,會(huì)繼續(xù)完善下去。希望這篇...

    Steve_Wang_ 評(píng)論0 收藏0
  • Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問題

    摘要:因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。舉個(gè)例子如果說服務(wù)器的帶寬只有,某個(gè)資源的下載速度是,系統(tǒng)啟動(dòng)個(gè)線程下載該資源并不會(huì)導(dǎo)致下載速度編程,所以在并發(fā)編程時(shí),需要考慮這些資源的限制。 最近私下做一項(xiàng)目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項(xiàng)目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Jav...

    yimo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<