<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    空間站

    北極心空

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks
    多線程
    線程:是指進程中的一個執行流程。
    線程與進程的區別:每個進程都需要操作系統為其分配獨立的內存地址空間,而同一進程中的所有線程在同一塊地址空間中工作,這些線程可以共享同一塊內存和系統資源。


    如何創建一個線程?

    創建線程有兩種方式,如下:
    1、 擴展java.lang.Thread類
    2、 實現Runnable接口
    Thread類代表線程類,它的兩個最主要的方法是:
    run()——包含線程運行時所執行的代碼
    Start()——用于啟動線程

    一個線程只能被啟動一次。第二次啟動時將會拋出java.lang.IllegalThreadExcetpion異常

    線程間狀態的轉換(如圖示)

    新建狀態:用new語句創建的線程對象處于新建狀態,此時它和其它的java對象一樣,僅僅在堆中被分配了內存
    就緒狀態:當一個線程創建了以后,其他的線程調用了它的start()方法,該線程就進入了就緒狀態。處于這個狀態的線程位于可運行池中,等待獲得CPU的使用權
    運行狀態:處于這個狀態的線程占用CPU,執行程序的代碼
    阻塞狀態:當線程處于阻塞狀態時,java虛擬機不會給線程分配CPU,直到線程重新進入就緒狀態,它才有機會轉到運行狀態。
    阻塞狀態分為三種情況:
    1、 位于對象等待池中的阻塞狀態:當線程運行時,如果執行了某個對象的wait()方法,java虛擬機就回把線程放到這個對象的等待池中
    2、 位于對象鎖中的阻塞狀態,當線程處于運行狀態時,試圖獲得某個對象的同步鎖時,如果該對象的同步鎖已經被其他的線程占用,JVM就會把這個線程放到這個對象的瑣池中。
    3、 其它的阻塞狀態:當前線程執行了sleep()方法,或者調用了其它線程的join()方法,或者發出了I/O請求時,就會進入這個狀態中。

    死亡狀態:當線程退出了run()方法,就進入了死亡狀態,該線程結束了生命周期。
    或者正常退出
    或者遇到異常退出
    Thread類的isAlive()方法判斷一個線程是否活著,當線程處于死亡狀態或者新建狀態時,該方法返回false,在其余的狀態下,該方法返回true.

    線程調度
    線程調度模型:分時調度模型和搶占式調度模型
    JVM采用搶占式調度模型。
    所謂的多線程的并發運行,其實是指宏觀上看,各個線程輪流獲得CPU的使用權,分別執行各自的任務。
    (線程的調度不是跨平臺,它不僅取決于java虛擬機,它還依賴于操作系統)

    如果希望明確地讓一個線程給另外一個線程運行的機會,可以采取以下的辦法之一
    1、 調整各個線程的優先級
    2、 讓處于運行狀態的線程調用Thread.sleep()方法
    3、 讓處于運行狀態的線程調用Thread.yield()方法
    4、 讓處于運行狀態的線程調用另一個線程的join()方法

    調整各個線程的優先級
    Thread類的setPriority(int)和getPriority()方法分別用來設置優先級和讀取優先級。
    如果希望程序能夠移值到各個操作系統中,應該確保在設置線程的優先級時,只使用MAX_PRIORITY、NORM_PRIORITY、MIN_PRIORITY這3個優先級。

    線程睡眠:當線程在運行中執行了sleep()方法時,它就會放棄CPU,轉到阻塞狀態。
    線程讓步:當線程在運行中執行了Thread類的yield()靜態方法時,如果此時具有相同優先級的其它線程處于就緒狀態,那么yield()方法將把當前運行的線程放到運行池中并使另一個線程運行。如果沒有相同優先級的可運行線程,則yield()方法什么也不做。
    Sleep()方法和yield()方法都是Thread類的靜態方法,都會使當前處于運行狀態的線程放棄CPU,把運行機會讓給別的線程,兩者的區別在于:
    1、sleep()方法會給其他線程運行的機會,而不考慮其他線程的優先級,因此會給較低線程一個運行的機會;yield()方法只會給相同優先級或者更高優先級的線程一個運行的機會。
    2、當線程執行了sleep(long millis)方法后,將轉到阻塞狀態,參數millis指定睡眠時間;當線程執行了yield()方法后,將轉到就緒狀態。
    3、sleep()方法聲明拋出InterruptedException異常,而yield()方法沒有聲明拋出任何異常
    4、sleep()方法比yield()方法具有更好的移植性

    等待其它線程的結束:join()
    當前運行的線程可以調用另一個線程的 join()方法,當前運行的線程將轉到阻塞狀態,直到另一個線程運行結束,它才恢復運行。

    定時器Timer:在JDK的java.util包中提供了一個實用類Timer, 它能夠定時執行特定的任務。

    線程的同步
    原子操作:根據Java規范,對于基本類型的賦值或者返回值操作,是原子操作。但這里的基本數據類型不包括long和double, 因為JVM看到的基本存儲單位是32位,而long 和double都要用64位來表示。所以無法在一個時鐘周期內完成。

    自增操作(++)不是原子操作,因為它涉及到一次讀和一次寫。

    原子操作:由一組相關的操作完成,這些操作可能會操縱與其它的線程共享的資源,為了保證得到正確的運算結果,一個線程在執行原子操作其間,應該采取其他的措施使得其他的線程不能操縱共享資源。

    同步代碼塊:為了保證每個線程能夠正常執行原子操作,Java引入了同步機制,具體的做法是在代表原子操作的程序代碼前加上synchronized標記,這樣的代碼被稱為同步代碼塊。

    同步鎖:每個JAVA對象都有且只有一個同步鎖,在任何時刻,最多只允許一個線程擁有這把鎖。

    當一個線程試圖訪問帶有synchronized(this)標記的代碼塊時,必須獲得 this關鍵字引用的對象的鎖,在以下的兩種情況下,本線程有著不同的命運。
    1、 假如這個鎖已經被其它的線程占用,JVM就會把這個線程放到本對象的鎖池中。本線程進入阻塞狀態。鎖池中可能有很多的線程,等到其他的線程釋放了鎖,JVM就會從鎖池中隨機取出一個線程,使這個線程擁有鎖,并且轉到就緒狀態。
    2、 假如這個鎖沒有被其他線程占用,本線程會獲得這把鎖,開始執行同步代碼塊。
    (一般情況下在執行同步代碼塊時不會釋放同步鎖,但也有特殊情況會釋放對象鎖
    如在執行同步代碼塊時,遇到異常而導致線程終止,鎖會被釋放;在執行代碼塊時,執行了鎖所屬對象的wait()方法,這個線程會釋放對象鎖,進入對象的等待池中)

    線程同步的特征:
    1、 如果一個同步代碼塊和非同步代碼塊同時操作共享資源,仍然會造成對共享資源的競爭。因為當一個線程執行一個對象的同步代碼塊時,其他的線程仍然可以執行對象的非同步代碼塊。(所謂的線程之間保持同步,是指不同的線程在執行同一個對象的同步代碼塊時,因為要獲得對象的同步鎖而互相牽制)
    2、 每個對象都有唯一的同步鎖
    3、 在靜態方法前面可以使用synchronized修飾符。
    4、 當一個線程開始執行同步代碼塊時,并不意味著必須以不間斷的方式運行,進入同步代碼塊的線程可以執行Thread.sleep()或者執行Thread.yield()方法,此時它并不釋放對象鎖,只是把運行的機會讓給其他的線程。
    5、 Synchronized聲明不會被繼承,如果一個用synchronized修飾的方法被子類覆蓋,那么子類中這個方法不在保持同步,除非用synchronized修飾。

    線程安全的類:
    1、 這個類的對象可以同時被多個線程安全的訪問。
    2、 每個線程都能正常的執行原子操作,得到正確的結果。
    3、 在每個線程的原子操作都完成后,對象處于邏輯上合理的狀態。

    釋放對象的鎖:
    1、 執行完同步代碼塊就會釋放對象的鎖
    2、 在執行同步代碼塊的過程中,遇到異常而導致線程終止,鎖也會被釋放
    3、 在執行同步代碼塊的過程中,執行了鎖所屬對象的wait()方法,這個線程會釋放對象鎖,進入對象的等待池。

    死鎖
    當一個線程等待由另一個線程持有的鎖,而后者正在等待已被第一個線程持有的鎖時,就會發生死鎖。JVM不監測也不試圖避免這種情況,因此保證不發生死鎖就成了程序員的責任。

    如何避免死鎖
    一個通用的經驗法則是:當幾個線程都要訪問共享資源A、B、C 時,保證每個線程都按照同樣的順序去訪問他們。

    線程通信
    Java.lang.Object類中提供了兩個用于線程通信的方法
    1、 wait():執行了該方法的線程釋放對象的鎖,JVM會把該線程放到對象的等待池中。該線程等待其它線程喚醒
    2、 notify():執行該方法的線程喚醒在對象的等待池中等待的一個線程,JVM從對象的等待池中隨機選擇一個線程,把它轉到對象的鎖池中。
    • 2803608e-b6f9-3ac8-8784-fad314b98cda-thumb
    • 描述:
    • 大小: 701.5 KB
    用synchronized修飾的方法被子類繼承并重寫,當子類運行其重寫后的synchronized方法時,相當于調用了2次用synchronized修飾的方法,這是怎么回事?


    (1)對于instance函數,關鍵字synchronized其實并不鎖定函數和代碼,它鎖定的是對象。請記住每個對象只有一個lock與之關聯。
    (2)Synchronized聲明不會被繼承,如果一個用synchronized修飾的方法被子類覆蓋,那么子類中這個方法不在保持同步,除非用synchronized修飾。
    (3)子類中重寫了synchronized修飾的方法后,當調用這個子類方法時,很顯然線程競爭的就是這個子類對象的lock,只有獲得這個lock的線程才會執行該方法體。
    (4)不明白你說的當子類運行其重寫后的synchronized方法時,相當于調用了2次用synchronized修飾的方法,怎么會呢?你是怎么調的?我很好奇!能不能把你的代碼貼出來看下?呵呵!
    posted on 2008-06-25 10:00 蘆葦 閱讀(248) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 亚洲视频在线观看免费| 成人免费无码大片A毛片抽搐色欲| 午夜一区二区免费视频| tom影院亚洲国产一区二区| 国产91色综合久久免费分享| 亚洲黄色免费在线观看| 国产免费AV片在线播放唯爱网| 亚洲人成电影网站| 国产卡二卡三卡四卡免费网址| 亚洲 欧洲 自拍 另类 校园| 韩国免费三片在线视频| 国产精品亚洲专区在线播放| 亚洲а∨天堂久久精品| 精品久久久久久国产免费了| 亚洲AV无码欧洲AV无码网站| 色天使色婷婷在线影院亚洲| 亚洲av麻豆aⅴ无码电影| 亚洲国产免费综合| 亚洲视频国产视频| 成人五级毛片免费播放| 三年片在线观看免费观看大全中国| 亚洲精品人成无码中文毛片| 嫩草在线视频www免费观看| 亚洲白色白色永久观看| 日本人成在线视频免费播放| 亚洲小视频在线观看| 成全影视免费观看大全二| 日韩毛片一区视频免费| 国产大片免费观看中文字幕| 亚洲精品中文字幕无乱码麻豆| 国产成人啪精品视频免费网| 日韩av无码免费播放| 亚洲一级免费毛片| 相泽亚洲一区中文字幕| 最好看最新的中文字幕免费| 色噜噜噜噜亚洲第一| 久久久久无码精品亚洲日韩| 永久免费看mv网站入口| 精品一区二区三区免费| 亚洲Av无码专区国产乱码DVD| 一个人免费观看视频www|