關於java多線程初試

一.什麼是多線程java

  在學習多進程以前得先明白兩個概念:
程序員

    進程:每一個進程都有獨立的代碼和數據空間(進程上下文),進程間的切換會有較大的開銷,一個進程包含1--n個線程,進程是資源分配的最小單位;安全

    線程:同一類線程共享代碼和數據空間,每一個線程有獨立的運行棧和程序計數器(PC),線程切換開銷小,線程是cpu調度的最小單位;多線程

    線程和進程同樣分爲五個階段:建立、就緒、運行、阻塞、終止。函數

    多進程是指操做系統能同時運行多個任務(程序)。學習

    多線程是指在同一程序中有多個順序流在執行。    spa

    多線程是多任務的一種特別的形式,但多線程使用了更小的資源開銷。操作系統

    這裏定義和線程相關的另外一個術語 - 進程:一個進程包括由操做系統分配的內存空間,包含一個或多個線程。一個線程不能獨立的存在,它必須是進程的一部分。一個  進程一直運行,直到全部的非守護線程都結束運行後才能結束。多線程能知足程序員編寫高效率的程序來達到充分利用 CPU 的目的。線程

二.怎樣開啓多線程對象

    在java中要想實現多線程,有兩種手段,一種是繼承Thread類,另一種是實現Runable接口。

    實現Runable接口:

    實現 Runnable,一個類只須要執行一個方法調用 run(),在建立一個實現 Runnable 接口的類以後,你能夠在類中實例化一個線程對象,新線程建立以後,你調用它      的 start() 方法它纔會運行。

    繼承Thread類:

    建立一個線程的第二種方法是建立一個新的類,該類繼承 Thread 類,而後建立一個該類的實例。繼承類必須重寫 run() 方法,該方法是新線程的入口點。它也必須       調用 start() 方法才能執行。

3、Thread和Runnable的區別   

    若是一個類繼承Thread,則不適合資源共享。可是若是實現了Runable接口的話,則很容易的實現資源共享。

     總結:

      實現Runnable接口比繼承Thread類所具備的優點:

      1):適合多個相同的程序代碼的線程去處理同一個資源

      2):能夠避免java中的單繼承的限制

      3):增長程序的健壯性,代碼能夠被多個線程共享,代碼和數據獨立

      4):線程池只能放入實現Runable或callable類線程,不能直接放入繼承Thread的類

 四.線程狀態的轉換

    建立:新建立了一個線程對象;

    就緒狀態(Runnable):線程對象建立後,其餘線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲 CPU的使用權。

    運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。

    阻塞狀態(Blocked):阻塞狀態是線程由於某種緣由放棄CPU使用權,暫時中止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的狀況分三種:

     等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。(wait會釋放持有的鎖)
     同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
     其餘阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、          或者I/O處理完畢時,線程從新轉入就緒狀態。(注意,sleep是不會釋放持有的鎖)
    死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。
五.經常使用方法
    sleep(long millis): 在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行)
      join():指等待t線程終止。
     yield():暫停當前正在執行的線程對象,並執行其餘線程,在大多數狀況下,yield()將致使線程從運行狀態轉到可運行狀態,但有可能沒有效果
    sleep()和yield()的區別):sleep()使當前線程進入停滯狀態,因此執行sleep()的線程在指定的時間內確定不會被執行;yield()只是使當前線程從新回到可執行狀態,因此執行yield()的線程有可能在進入到可執行狀態後立刻又被執行。
    sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其餘線程,可是對象的鎖依然保持,所以休眠時間結束後會自動恢復。wait()是Object類的方法,調用對象的wait()方法致使當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),若是線程從新得到對象的鎖就能夠進入就緒狀態。
    sleep()睡眠時,保持對象鎖,仍然佔有該鎖;
    wait()睡眠時,釋放對象鎖。
    notify(): 通知一個線程繼續運行,得到鎖標記。
六.線程安全
   通常理解爲線程同步,線程同步的目的是爲了保護多個線程反問一個資源時對資源的破壞,線程同步方法是經過鎖來實現,每一個對象都有切僅有一個鎖,這個鎖與一個     特定的對象關聯,線程一旦獲取了對象鎖,其餘訪問該對象的線程就沒法再訪問該對象的其餘非同步方法,當多個線程等待一個對象鎖時,沒有獲取到鎖的線程將發生阻       塞,死鎖是線程間相互等待鎖鎖形成的,在實際中發生的機率很是的小。真讓你寫個死鎖程序,不必定好使,呵呵。可是,一旦程序發生死鎖,程序將死掉。
    保持線程同步的方法通常就是加鎖,如synchronized關鍵字。synchronized關鍵字能夠做爲函數的修飾符,也可做爲函數內的語句,也就是平時說的同步方法和同步     語句塊。若是再細的分類,synchronized可做用於instance變量、object reference(對象引用)、static函數和class literals(類名稱字面常量)身上。只要一個線程訪問了其中   的一個synchronized方法,其它線程不能同時訪問這個對象中任何一個synchronized方法。
相關文章
相關標籤/搜索