亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

huangjinnan / 1106人閱讀

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

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

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

【java線程的運行機制

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

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),此時它和其他java對象一樣,僅僅在堆中被分配了內(nèi)存。

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

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

阻塞狀態(tài):線程因為某些原因放棄了CPU暫停執(zhí)行。此時線程放棄CPU的執(zhí)行權(quán),直到進入就緒狀態(tài)才可能再次變?yōu)檫\行狀態(tài)。阻塞狀態(tài)3中情況:

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

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

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

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

【線程調(diào)度

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

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

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

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

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

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

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

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

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

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

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

可見性:當多個線程訪問同一變量時,一個線程修改了該變量的值,其他線程能立即看到修改后的值。

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

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

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

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

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

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

以下情況線程釋放鎖:

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

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

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

以下情況線程不會釋放鎖:

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

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

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

【線程通信

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

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

補充:

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

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

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

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

【中斷阻塞

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

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

并發(fā)編程的知識非常復(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)知識,最后用一個實際項目來完成這部分知識的學(xué)習(xí)。

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/68063.html

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

    yimo 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<