最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析 Java多線程

 更新時間:2020年09月26日 11:03:22   作者:城北有個混子  
這篇文章主要介紹了Java多線程的相關資料,幫助大家更好的理解和學習Java線程相關知識,感興趣的朋友可以了解下

什么是進程

  當一個程序進入內(nèi)存中運行起來它就變?yōu)橐粋€進程。因此,進程就是一個處于運行狀態(tài)的程序。同時進程具有獨立功能,進程是操作系統(tǒng)進行資源分配和調(diào)度的獨立單位。

什么是線程

  線程是進程的組成部分。通常情況下,一個進程可擁有多個線程,而一個線程只能擁有一個父進程。

  線程可以擁有自己的堆棧、自己的程序計數(shù)器及自己的局部變量,但是線程不能擁有系統(tǒng)資源,它與其父進程的其他線程共享進程中的全部資源,這其中包括進程的代碼段、數(shù)據(jù)段、堆空間以及一些進程級的資源(例如,打開的文件等)。

  線程是進程的執(zhí)行單元,是CPU調(diào)度和分派的基本單位,當進程被初始化之后,主線程就會被創(chuàng)建。同時如果有需要,還可以在程序執(zhí)行過程中創(chuàng)建出其他線程,這些線程之間也是相互獨立的,并且在同一進程中并發(fā)執(zhí)行。因此一個進程中可以包含多個線程,但是至少要包含一個線程,即主線程。

Java中的線程

  Java 中使用Thread類表示一個線程。所有的線程對象都必須是Thread或其子類的對象。Thread 類中的 run 方法是該線程的執(zhí)行代碼。讓我們來看一個實例:

public class Ticket extends Thread{
  // 重寫run方法
  public void run() {
    for (int i = 0; i < 20; i++) {
      System.out.println(getName() + ": " + i);
    }
  }
}
public class TestThread {
  public static void main(String[] args) {
    // 1.創(chuàng)建線程
    Thread thread1 = new Ticket();
    Thread thread2 = new Ticket();
    
    // 2.啟動線程
    thread1.start();
    thread2.start();
  }
}

運行結(jié)果如下:

 通過上面的代碼和運行結(jié)果,我們可以得到:

線程運行的幾個特點

  1.同一進程下不同線程的調(diào)度不由程序控制。線程的執(zhí)行是搶占式的,運行的順序和線程的啟動順序是無關的,當前運行的線程隨時都可能被掛起,然后其他進程搶占運行。

  2.線程獨享自己的堆棧程序計數(shù)器和局部變量。兩個進程的局部變量互不干擾,各自的執(zhí)行順序也是互不干擾。

  3.兩個線程并發(fā)執(zhí)行。兩個線程同時向前推進,并沒有說執(zhí)行完一個后再執(zhí)行另一個。

start()方法和run()方法

  啟動一個線程必須調(diào)用Thread 類的 start()方法,使該線程處于就緒狀態(tài),這樣該線程就可以被處理器調(diào)度。

   run()方法是一個線程所關聯(lián)的執(zhí)行代碼,無論是派生自 Thread類的線程類,還是實現(xiàn)Runnable接口的類,都必須實現(xiàn)run()方法,run()方法里是我們需要線程所執(zhí)行的代碼。

  實現(xiàn)多線程必須調(diào)用Thread 類的 start()方法來啟動線程,使線程處于就緒狀態(tài)隨時供CPU調(diào)度。如果直接調(diào)用run()方法的話,只是調(diào)用了Thread類的一個普通方法,會立即執(zhí)行該方法中的代碼,并沒有實現(xiàn)多線程技術(shù)。

Java中多線程的實現(xiàn)方法

  在Java中有三種方法實現(xiàn)多線程。

    第一種方法:使用Thread類或者使用一個派生自Thread 類的類構(gòu)建一個線程。

    第二種方法:實現(xiàn)Runnable 接口來構(gòu)建一個線程。(推薦使用)

    第三種方法:實現(xiàn)Callable 接口來構(gòu)建一個線程。(有返回值)

第一種方法

  使用Thread類或者使用一個派生自Thread 類的類構(gòu)建一個線程。

public class Ticket extends Thread{
  // 重寫run方法
  public void run() {
    for (int i = 0; i < 20; i++) {
      System.out.println(getName() + ": " + i);
    }
  }
}
public class TestThread {
  public static void main(String[] args) {
    // 1.創(chuàng)建線程
    Thread thread1 = new Ticket();
    Thread thread2 = new Ticket();
    
    // 2.啟動線程
    thread1.start();
    thread2.start();
  }
}

  看上面的代碼,我們創(chuàng)建了一個Ticket類,它繼承了Thread類,重寫了Thread類的run方法。然后我們用Ticket類創(chuàng)建了兩個線程,并且啟動了它們。但我們不推薦使用這種方法,因為一個類繼承了Thread類,那它就沒有辦法繼承其他類了,這對較為復雜的程序開發(fā)是不利的。

第二種方法

  實現(xiàn)Runnable 接口來構(gòu)建一個線程。

public class Ticket implements Runnable{
  // 重寫run方法
  public void run() {
    for (int i = 0; i < 20; i++) {
      System.out.println(Thread.currentThread().getName() + ": " + i);
    }
  }
}
public class TestThread {
  public static void main(String[] args) {
    // 1.創(chuàng)建線程
    Ticket t1 = new Ticket();
    Ticket t2 = new Ticket();
    Thread thread1 = new Thread(t1, "買票1號");
    Thread thread2 = new Thread(t2, "買票2號");
    
    // 2.啟動線程
    thread1.start();
    thread2.start();
  }
}

  我們創(chuàng)建了一個Ticket類,實現(xiàn)了Runnable接口,在該類中實現(xiàn)了run方法。在啟動線程前,我們要創(chuàng)建一個線程對象,不同的是我們要將一個實現(xiàn)了Runnable接口的類的對象作為Thread類構(gòu)造方法的參數(shù)傳入,以構(gòu)建線程對象。構(gòu)造方法Thread的第二個參數(shù)用來指定該線程的名字,通過Thread.currentThread().getName()可獲取當前線程的名字。

  在真實的項目開發(fā)中,推薦使用實現(xiàn)Runnable接口的方法進行多線程編程。因為這樣既可以實現(xiàn)一個線程的功能,又可以更好地復用其他類的屬性和方法。

第三種方法

  實現(xiàn)Callable 接口來構(gòu)建一個線程。

public class TestThread {
  public static void main(String[] args) {  
    // 1.創(chuàng)建Callable的實例
    Callable<String> callable = new Callable<String>() {
      @Override
      public String call() throws Exception {
        Thread.sleep(7000);
        return "我結(jié)束了";
      }
    };
    
    // 2.通過FutureTask接口的實例包裝Callable的實例
    FutureTask<String> futureTask = new FutureTask<String>(callable);
    
    // 3.創(chuàng)建線程并啟動
    new Thread(futureTask).start();
    
    // 4.獲得結(jié)果并打印
    try {
      System.out.println(futureTask.get());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

  首先我們用匿名內(nèi)部類創(chuàng)建了一個實現(xiàn)Callable接口的類的對象,然后通過FutureTask 的實例包裝了Callable的實例,這樣我們就可以通過一個Thread 對象在新線程中執(zhí)行call()方法,同時又可以通過get方法獲取到call()的返回值。然后創(chuàng)建線程并啟動它,最后在線程執(zhí)行完執(zhí)行完call()方法后得到返回值并打印。

  我們來看一下Callable的源碼:

public interface Callable<V> {
  /**
   * Computes a result, or throws an exception if unable to do so.
   *
   * @return computed result
   * @throws Exception if unable to compute a result
   */
  V call() throws Exception;
}

  從Callable 的定義可以看出,Callable接口是一個泛型接口,它定義的call()方法類似于Runnable 的run()方法,是線程所關聯(lián)的執(zhí)行代碼。但是與run()方法不同的是,call()方法具有返回值,并且泛型接口的參數(shù)V指定了call()方法的返回值類型。同時,如果call()方法得不到返回值將會拋出一個異常,而在Runnable的run()方法中不能拋出異常。

如何獲得call()方法的返回值

  通過Future接口來獲取。Future接口定義了一組對 Runnable 或者Callable 任務的執(zhí)行結(jié)果進行取消、查詢、獲取、設置的操作。其中g(shù)et方法用于獲取call()的返回值,它會發(fā)生阻塞,直到call()返回結(jié)果。

這樣的線程調(diào)用與直接同步調(diào)用函數(shù)有什么差異

  在上面的例子中,通過future.get()獲取 call()的返回值時,由于call方法中會 sleep 7s,所以在執(zhí)行future.get()的時候主線程會被阻塞而什么都不做,等待call()執(zhí)行完并得到返回值。但是這與直接調(diào)用函數(shù)獲取返回值還是有本質(zhì)區(qū)別的。

  因為call()方法是運行在其他線程里的,在這個過程中主線程并沒有被阻塞,還是可以做其他事情的,除非執(zhí)行future.get()去獲取 call()的返回值時主線程才會被阻塞。所以當調(diào)用了Thread.start()方法啟動 Callable 線程后主線程可以執(zhí)行別的工作,當需要call()的返回值時再去調(diào)用future.get()獲取,此時call()方法可能早已執(zhí)行完畢,這樣就可以既確保耗時操作在工作線程中完成而不阻擋主線程,又可以得到線程執(zhí)行結(jié)果的返回值。而直接調(diào)用函數(shù)獲取返回值是一個同步操作,該函數(shù)本身就是運行在主線程中,所以一旦函數(shù)中有耗時操作,必然會阻擋主線程。

以上就是淺析 Java多線程的詳細內(nèi)容,更多關于Java多線程的資料請關注腳本之家其它相關文章!

相關文章

  • 使用JDBC連接Mysql 8.0.11出現(xiàn)了各種錯誤的解決

    使用JDBC連接Mysql 8.0.11出現(xiàn)了各種錯誤的解決

    這篇文章主要介紹了使用JDBC連接Mysql 8.0.11出現(xiàn)了各種錯誤的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Java中循環(huán)冗余校驗(CRC32)的實現(xiàn)

    Java中循環(huán)冗余校驗(CRC32)的實現(xiàn)

    CRC校驗實用程序庫在數(shù)據(jù)存儲和數(shù)據(jù)通訊領域,為了保證數(shù)據(jù)的正確,就不得不采用檢錯的手段,下面這篇文章主要給大家介紹了關于Java中循環(huán)冗余校驗(CRC32)實現(xiàn)的相關資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-10-10
  • Java SpringBoot在RequestBody中高效的使用枚舉參數(shù)原理案例詳解

    Java SpringBoot在RequestBody中高效的使用枚舉參數(shù)原理案例詳解

    這篇文章主要介紹了Java SpringBoot在RequestBody中高效的使用枚舉參數(shù)原理案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Java service層獲取HttpServletRequest工具類的方法

    Java service層獲取HttpServletRequest工具類的方法

    今天小編就為大家分享一篇關于Java service層獲取HttpServletRequest工具類的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • java 方法重寫與權(quán)限修飾符以及多態(tài)和抽象類詳解概念和用法

    java 方法重寫與權(quán)限修飾符以及多態(tài)和抽象類詳解概念和用法

    重寫是子類對父類的允許訪問的方法的實現(xiàn)過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫,權(quán)限修飾符用于控制被修飾變量、方法、類的可見范圍,說明了面向?qū)ο蟮姆庋b性,所以我們要適用他們盡可能的讓權(quán)限降到最低,從而安全性提高
    2021-10-10
  • 聊聊Spring Cloud Cli 初體驗

    聊聊Spring Cloud Cli 初體驗

    這篇文章主要介紹了聊聊Spring Cloud Cli 初體驗,SpringBoot CLI 是spring Boot項目的腳手架工具。非常具有實用價值,需要的朋友可以參考下
    2018-04-04
  • IDEA設置Maven自動編譯model的實現(xiàn)方法

    IDEA設置Maven自動編譯model的實現(xiàn)方法

    本文主要介紹了IDEA設置Maven自動編譯model的實現(xiàn)方法, maven結(jié)構(gòu)的項目,我們在每次修改代碼后都會需要手動編譯,本文就可以解決這個問題,感興趣的可以了解一下
    2023-08-08
  • java實現(xiàn)本地日期時間處理

    java實現(xiàn)本地日期時間處理

    這篇文章主要介紹了本地日期時間處理的程序,實現(xiàn)了下面的功能,大家參考使用吧
    2014-01-01
  • IDEA找不到jdk該如何解決

    IDEA找不到jdk該如何解決

    這篇文章主要給大家介紹了關于IDEA找不到jdk該如何解決的相關資料,剛安裝好IDEA后,我們運行一個項目時候,有時候會遇到顯示找不到Java的JDK,需要的朋友可以參考下
    2023-11-11
  • springboot+vue?若依項目在windows2008R2企業(yè)版部署流程分析

    springboot+vue?若依項目在windows2008R2企業(yè)版部署流程分析

    這篇文章主要介紹了springboot+vue?若依項目在windows2008R2企業(yè)版部署流程,本次使用jar包啟動后端,故而準備打包后的jar文件,需要的朋友可以參考下
    2022-12-12

最新評論

巴马| 马公市| 赤峰市| 长沙县| 虹口区| 噶尔县| 咸阳市| 山东省| 新郑市| 南开区| 肇东市| 厦门市| 荆州市| 阳新县| 光泽县| 揭阳市| 息烽县| 祁连县| 正安县| 金堂县| 扶绥县| 延庆县| 丰宁| 定西市| 高台县| 聂荣县| 霍城县| 岚皋县| 德保县| 宁乡县| 鄂托克旗| 红安县| 普兰店市| 吉安市| 内丘县| 阳谷县| 都兰县| 祁阳县| 乌拉特后旗| 万源市| 乳山市|