欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

學(xué)習(xí)Java多線程之線程定義、狀態(tài)和屬性

 更新時間:2016年02月29日 09:59:21   作者:劉望舒  
這篇文章主要為大家詳細(xì)介紹了Java多線程之線程定義、狀態(tài)和屬性,感興趣的小伙伴們可以參考一下

一 、線程和進(jìn)程

1. 什么是線程和進(jìn)程的區(qū)別:
線程是指程序在執(zhí)行過程中,能夠執(zhí)行程序代碼的一個執(zhí)行單元。在java語言中,線程有四種狀態(tài):運(yùn)行 、就緒、掛起和結(jié)束。
進(jìn)程是指一段正在執(zhí)行的程序。而線程有事也被成為輕量級的進(jìn)程,他得程序執(zhí)行的最小單元,一個進(jìn)程可以擁有多個線程,各個線程之間共享程序的內(nèi)功空間(代碼段、數(shù)據(jù)段和堆空間)及一些進(jìn)程級的資源(例如打開的文件),但是各個線程都擁有自己的??臻g。
2. 為何要使用多進(jìn)程
在操作系統(tǒng)級別上來看主要有以下幾個方面:
- 使用多線程可以減少程序的響應(yīng)時間,如果某個操作和耗時,或者陷入長時間的等待,此時程序講不會響應(yīng)鼠標(biāo)和鍵盤等的操作,使用多線程后可以把這個耗時的線程分配到一個單獨(dú)的線程去執(zhí)行,從而使程序具備了更好的交互性。
- 與進(jìn)程相比,線程創(chuàng)建和切換開銷更小,同時多線程在數(shù)據(jù)共享方面效率非常高。
- 多CPU或者多核計(jì)算機(jī)本身就具備執(zhí)行多線程的能力,如果使用單個進(jìn)程,將無法重復(fù)利用計(jì)算機(jī)資源,造成資源的巨大浪費(fèi)。在多CPU計(jì)算機(jī)使用多線程能提高CPU的利用率。
- 使用多線程能簡化程序的結(jié)構(gòu),使程序便于理解和維護(hù)

二、創(chuàng)建線程
多線程的實(shí)現(xiàn)一般有以下三種方法其中前兩種為最常用的方法:
1. 繼承Thread類,重寫run()方法
Thread本質(zhì)上也是實(shí)現(xiàn)了Runnable接口的一個實(shí)例。需要注意的是調(diào)用start()方法后并不是是立即的執(zhí)行多線程的代碼,而是使該線程變?yōu)榭蛇\(yùn)行態(tài),什么時候運(yùn)行多線程代碼是由操作系統(tǒng)決定的。
以下是主要步驟:
(1)定義Thread類的子類,并重寫該類的run方法,該run方法的方法體就代表了線程要完成的任務(wù)。因此把run()方法稱為執(zhí)行體。
(2)創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建了線程對象。
(3)調(diào)用線程對象的start()方法來啟動該線程。

public class TestThread extends Thread{ 
  public void run() {
      System.out.println("Hello World");
    } 
  public static void main(String[] args) {
    Thread mThread = new TestThread();
    mThread.start(); 
  } 
}

2. 實(shí)現(xiàn)Runnable接口,并實(shí)現(xiàn)該接口的run()方法
以下是主要步驟:
(1)自定義類并實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)run()方法。
(2)創(chuàng)建Thread子類的實(shí)例,用實(shí)現(xiàn)Runnable接口的對象作為參數(shù)實(shí)例化該Thread對象。
(3)調(diào)用Thread的start()方法來啟動該線程。

public class TestRunnable implements Runnable {
  public void run() { 
      System.out.println("Hello World");
    } 
}

public class TestRunnable {
  public static void main(String[] args) {
    TestRunnable mTestRunnable = new TestRunnable();   
    Thread mThread = new Thread(mTestRunnable);
    mThread.start(); 
  } 
}

3. 實(shí)現(xiàn)Callable接口,重寫call()方法
Callable接口實(shí)際是屬于Executor框架中的功能類,Callable接口與Runnable接口的功能類似,但提供了比Runnable更強(qiáng)大的功能,主要表現(xiàn)為以下的3點(diǎn):
(1)Callable可以在任務(wù)接受后提供一個返回值,Runnable無法提供這個功能。
(2)Callable中的call()方法可以拋出異常,而Runnable的run()方法不能拋出異常。
(3)運(yùn)行Callable可以拿到一個Future對象,F(xiàn)uture對象表示伊布計(jì)算的結(jié)果,他提供了檢查計(jì)算是否完成的方法。由于線程屬于異步計(jì)算模型,因此無法從別的線程中得到函數(shù)的返回值,在這種情況下就可以使用Future來監(jiān)視目標(biāo)線程調(diào)用call()方法的情況,但調(diào)用Future的get()方法以獲取結(jié)果時,當(dāng)前線程就會阻塞,知道call()方法的返回結(jié)果。

public class TestCallable { 
  //創(chuàng)建線程類
  public static class MyTestCallable implements Callable { 
    public String call() throws Exception { 
       retun "Hello World";
      } 
    } 
public static void main(String[] args) { 
    MyTestCallable mMyTestCallable= new MyTestCallable(); 
    ExecutorService mExecutorService = Executors.newSingleThreadPool(); 
    Future mfuture = mExecutorService.submit(mMyTestCallable); 
    try { 
    //等待線程結(jié)束,并返回結(jié)果
      System.out.println(mfuture.get()); 
    } catch (Exception e) { 
      e.printStackTrace();
    } 
  } 
} 

上述程序的輸出結(jié)果為:Hello World

在這三種方式中,一般推薦實(shí)現(xiàn)Runnable接口的方式,其原因是:首先,Thread類定義了多種方法可以被派生類使用重寫,但是只有run()方法是必須被重寫的,實(shí)現(xiàn)這個線程的主要功能,這也是實(shí)現(xiàn)Runnable接口需要的方法。其次,一個類應(yīng)該在他們需要加強(qiáng)或者修改時才會被繼承。因此如果沒有必要重寫Thread類的其他方法,那么在這種情況下最好是用實(shí)現(xiàn)Runnable接口的方式。

三、中斷線程
當(dāng)線程的run()方法執(zhí)行方法體中的最后一條語句后,并經(jīng)由執(zhí)行return語句返回時,或者出現(xiàn)在方法中沒有捕獲的異常時線程將終止。在java早期版本中有一個stop方法,其他線程可以調(diào)用它終止線程,但是這個方法現(xiàn)在已經(jīng)被棄用了。
interrupt方法可以用來請求終止線程,當(dāng)一個線程調(diào)用interrupt方法時,線程的中斷狀態(tài)將被置位。這是沒有個線程都具有的boolean標(biāo)志,每個線程都應(yīng)該不時的檢查這個標(biāo)志,來判斷線程是否被中斷。
要想弄清線程是否被置位,可以調(diào)用Thread.currentThread().isInterrupted():

while(!Thread.currentThread().isInterrupted()){
do something
}

但是如果一個線程被阻塞,就無法檢測中斷狀態(tài)。這是產(chǎn)生InterruptedException的地方。當(dāng)一個被阻塞的線程(調(diào)用sleep或者wait)上調(diào)用interrupt方法。阻塞調(diào)用將會被InterruptedException中斷。
如果每次迭代之后都調(diào)用sleep方法(或者其他可中斷的方法),isInterrupted檢測就沒必要也沒用處了,如果在中斷狀態(tài)被置位時調(diào)用sleep方法,它不會休眠反而會清除這一狀態(tài)并拋出InterruptedException。所以如果在循環(huán)中調(diào)用sleep,不要去檢測中斷狀態(tài),只需捕獲InterruptedException。
在很多發(fā)布的代碼中會發(fā)現(xiàn)InterruptedException被抑制在很低的層次上:

void myTask(){
...
try{
sleep(50)
}catch(InterruptedException e){
...
}
}

不要這樣做,如果不認(rèn)為catch中做一處理有什么好處的話,有兩種合理的選擇:

在catch中調(diào)用Thread.currentThread().interrup()來設(shè)置中斷狀態(tài)。調(diào)用者可以對其進(jìn)行檢測
更好的選擇用throw InterruptedException標(biāo)記你的方法,不采用try語句塊來捕獲已成。這樣調(diào)用者可以捕獲這個異常:

void myTask()throw InterruptedException{
sleep(50)
}

四、線程的狀態(tài)

(1). 新建狀態(tài)(New):新創(chuàng)建了一個線程對象。
(2). 就緒狀態(tài)(Runnable):線程對象創(chuàng)建后,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,變得可運(yùn)行,等待獲取CPU的使用權(quán)。
(3). 運(yùn)行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。
(4). 阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán),暫時停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞的情況分三種:
- 等待阻塞:運(yùn)行的線程執(zhí)行wait()方法,JVM會把該線程放入等待池中。
- 同步阻塞:運(yùn)行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。
- 其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時,JVM會把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)。
(5). 死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。

五、線程的優(yōu)先級和守護(hù)線程

1. 線程優(yōu)先級
在java中,每一個線程有一個優(yōu)先級,默認(rèn)情況下,一個線程繼承它父類的優(yōu)先級。可以用setPriority方法提高或降低任何一個線程優(yōu)先級。可以將優(yōu)先級設(shè)置在MIN_PRIORITY(在Thread類定義為1)與MAX_PRIORITY(在Thread類定義為10)之間的任何值。線程的默認(rèn)優(yōu)先級為NORM_PRIORITY(在Thread類定義為5)。
盡量不要依賴優(yōu)先級,如果確實(shí)要用,應(yīng)該避免初學(xué)者常犯的一個錯誤。如果有幾個高優(yōu)先級的線程沒有進(jìn)入非活動狀態(tài),低優(yōu)先級線程可能永遠(yuǎn)也不能執(zhí)行。每當(dāng)調(diào)度器決定運(yùn)行一個新線程時,首先會在具有搞優(yōu)先級的線程中進(jìn)行選擇,盡管這樣會使低優(yōu)先級的線程完全餓死。

2. 守護(hù)線程

調(diào)用setDaemon(true);將線程轉(zhuǎn)換為守護(hù)線程。守護(hù)線程唯一的用途就是為其他線程提供服務(wù)。計(jì)時線程就是一個例子,他定時發(fā)送信號給其他線程或者清空過時的告訴緩存項(xiàng)的線程。當(dāng)只剩下守護(hù)線程時,虛擬機(jī)就退出了,由于如果只剩下守護(hù)線程,就沒必要繼續(xù)運(yùn)行程序了。
另外JVM的垃圾回收、內(nèi)存管理等線程都是守護(hù)線程。還有就是在做數(shù)據(jù)庫應(yīng)用時候,使用的數(shù)據(jù)庫連接池,連接池本身也包含著很多后臺線程,監(jiān)控連接個數(shù)、超時時間、狀態(tài)等等。

以上就是關(guān)于Java多線程的線程定義、狀態(tài)和屬性,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • SpringCloud?服務(wù)注冊中的nacos實(shí)現(xiàn)過程

    SpringCloud?服務(wù)注冊中的nacos實(shí)現(xiàn)過程

    這篇文章主要介紹了SpringCloud?服務(wù)注冊之nacos實(shí)現(xiàn)過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Java設(shè)計(jì)模式七大原則之合成復(fù)用原則詳解

    Java設(shè)計(jì)模式七大原則之合成復(fù)用原則詳解

    合成復(fù)用原則(Composite Reuse Principle),即盡量使用組合/聚合的方式,而不是使用繼承。本文將為大家具體介紹一下Java設(shè)計(jì)模式七大原則之一的合成復(fù)用原則,需要的可以參考一下
    2022-02-02
  • 詳解java為什么不允許類多重繼承卻允許接口多重繼承

    詳解java為什么不允許類多重繼承卻允許接口多重繼承

    這篇文章主要介紹了java為什么不允許類多重繼承卻允許接口多重繼承,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Spring Boot如何使用EhCache演示

    Spring Boot如何使用EhCache演示

    這篇文章主要介紹了Spring Boot如何使用EhCache演示,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 淺談Java并發(fā)編程基礎(chǔ)知識

    淺談Java并發(fā)編程基礎(chǔ)知識

    這篇文章主要介紹了淺談Java并發(fā)編程基礎(chǔ)知識,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • SpringMVC底層執(zhí)行流程及原理解析

    SpringMVC底層執(zhí)行流程及原理解析

    這篇文章主要介紹了SpringMVC底層執(zhí)行流程及原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Mybatis第三方PageHelper分頁插件的使用與原理

    Mybatis第三方PageHelper分頁插件的使用與原理

    提到插件相信大家都知道,插件的存在主要是用來改變或者增強(qiáng)原有的功能,MyBatis中也一樣,下面這篇文章主要給大家介紹了關(guān)于Mybatis第三方PageHelper分頁插件的使用與原理,需要的朋友可以參考下
    2022-02-02
  • Java的函數(shù)式接口@FunctionalInterface的使用說明

    Java的函數(shù)式接口@FunctionalInterface的使用說明

    這篇文章主要介紹了Java的函數(shù)式接口@FunctionalInterface的使用說明,我們常用的一些接口Callable、Runnable、Comparator等在JDK8中都添加了@FunctionalInterface注解,需要的朋友可以參考下
    2024-01-01
  • SpringBoot靜態(tài)資源配置原理(源碼分析)

    SpringBoot靜態(tài)資源配置原理(源碼分析)

    這篇文章主要介紹了SpringBoot靜態(tài)資源配置原理(源碼分析),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 用StopWatch優(yōu)雅替代currentTimeMillis計(jì)算程序執(zhí)行耗時

    用StopWatch優(yōu)雅替代currentTimeMillis計(jì)算程序執(zhí)行耗時

    別再用System.currentTimeMillis()計(jì)算程序執(zhí)行耗時了,擁抱StopWatch優(yōu)雅來優(yōu)雅的計(jì)算,代碼更簡潔效率更高,本文帶你了解StopWatch的使用
    2021-09-09

最新評論