亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java 線程對比(Thread,Runnable,Callable)實例詳解

 更新時間:2016年12月22日 08:53:24   作者:android_小路  
這篇文章主要介紹了Java 線程(Thread,Runnable,Callable)實例詳解的相關(guān)資料,這里對java 線程的三種方法進(jìn)行了對比,需要的朋友可以參考下

Java 線程對比Thread,Runnable,Callable

java 使用 Thread 類代表線程,所有現(xiàn)場對象都必須是 Thread 類或者其子類的實例。每個線程的作用是完成一定的任務(wù),實際上就是執(zhí)行一段程序流。java 使用線程執(zhí)行體來代表這段程序流。

1.繼承Thread 類創(chuàng)建線程

啟動多線程的步驟如下:

(1)定義Thread 類的子類,并重寫該類的run() 方法,該run() 方法的方法體就代表類線程需要完成的任務(wù)。因此把run() 方法稱為線程執(zhí)行體。
(2)創(chuàng)建 Thread 子類的實例,即創(chuàng)建線程對象。
(3)調(diào)用線程的star()方法來啟動該線程。

相關(guān)代碼如下:

/**
   * 繼承 thread 的內(nèi)部類,以買票例子
   */
  public class FirstThread extends Thread{
    private int i;
    private int ticket = 10;

    @Override
    public void run() {
      for (;i<20;i++) {
        //當(dāng)繼承thread 時,直接使用this 可以獲取當(dāng)前的線程,getName() 獲取當(dāng)前線程的名字
//        Log.d(TAG,getName()+" "+i);

        if(this.ticket>0){
          Log.e(TAG, getName() + ", 賣票:ticket=" + ticket--);
        }
      }

    }
  }

  private void starTicketThread(){
    Log.d(TAG,"starTicketThread, "+Thread.currentThread().getName());

    FirstThread thread1 = new FirstThread();
    FirstThread thread2 = new FirstThread();
    FirstThread thread3 = new FirstThread();

    thread1.start();
    thread2.start();
    thread3.start();

    //開啟3個線程進(jìn)行買票,每個線程都賣了10張,總共就30張票

  }

運行結(jié)果:

運行結(jié)果

可以看到 3 個線程輸入的 票數(shù)變量不連續(xù),注意:ticket 是 FirstThread 的實例屬性,而不是局部變量,但是因為程序每次創(chuàng)建線程對象都需要創(chuàng)建一個FirstThread 的對象,所有多個線程不共享該實例的屬性。

2.實現(xiàn) Runnable 接口創(chuàng)建線程

注意:public class Thread implements Runnable

(1)定義 Runnable 接口的實現(xiàn)類,并重寫該接口的run()方法,該run() 方法的方法體同樣是該線程的線程執(zhí)行體。
(2)創(chuàng)建 Runnable 實例類的實例,此實例作為 Thread 的 target 來創(chuàng)建Thread 對象,該Thread 對象才是真正的對象。

相關(guān)代碼如下:

/**
   * 實現(xiàn) runnable 接口,創(chuàng)建線程類
   */
  public class SecondThread implements Runnable{

    private int i;
    private int ticket = 100;

    @Override
    public void run() {
      for (;i<20;i++) {
        //如果線程類實現(xiàn) runnable 接口
        //獲取當(dāng)前的線程,只能用 Thread.currentThread() 獲取當(dāng)前的線程名
        Log.d(TAG,Thread.currentThread().getName()+" "+i);

        if(this.ticket>0){
          Log.e(TAG, Thread.currentThread().getName() + ", 賣票:ticket=" + ticket--);
        }
      }
    }
  }


  private void starTicketThread2(){
    Log.d(TAG,"starTicketThread2, "+Thread.currentThread().getName());

    SecondThread secondThread = new SecondThread();

    //通過new Thread(target,name)創(chuàng)建新的線程
    new Thread(secondThread,"買票人1").start();
    new Thread(secondThread,"買票人2").start();
    new Thread(secondThread,"買票人3").start();

    //雖然是開啟了3個線程,但是一共只買了100張票
  }

運行結(jié)果:

這里寫圖片描述

可以看到 3 個線程輸入的 票數(shù)變量是連續(xù)的,采用 Runnable 接口的方式創(chuàng)建多個線程可以共享線程類的實例的屬性。這是因為在這種方式下,程序所創(chuàng)建的Runnable 對象只是線程的 target ,而多個線程可以共享同一個 target,所以多個線程可以共享同一個線程類(實際上應(yīng)該是該線程的target 類)的實例屬性。

3.使用 Callable 和Future 創(chuàng)建線程

從 java 5 開始,Java 提供了 Callable 接口,該接口是runnable 的增強版,Callable 提供類一個 call() 方法可以作為線程執(zhí)行體,但是call() 方法的功能更強大。

(1) call() 方法可以有返回值
(2) call() 方法可以聲明拋出異常

因此我們完全可以提供一個callable 對象作為Thread的 target ,而該線程的執(zhí)行體就是該callable 對象的call() 方法。同時 java 5 提供了 Future 接口 來代表Callable 接口里 call() 方法的返回值,并且提供了一個 futureTask 的實現(xiàn)類,該實現(xiàn)類實現(xiàn)類 future 接口,并實現(xiàn)了runnable 接口—可以作為Thread 類的target.

啟動步驟如下:

(1)創(chuàng)建callable接口的實現(xiàn)類,并實現(xiàn)call() 方法,該call() 方法將作為線程的執(zhí)行體,且該call() 方法是有返回值的。
(2)創(chuàng)建 callable實現(xiàn)類的實例,使用 FutureTask 類來包裝Callable對象,該FutureTask 對象封裝 call() 方法的返回值。
(3)使用FutureTask 對象作為Thread對象的target創(chuàng)建并啟動新線程。
(4)調(diào)用FutureTask對象的get()方法來獲取子線程執(zhí)行結(jié)束后的返回值。

相關(guān)代碼如下:

/**
   * 使用callable 來實現(xiàn)線程類
   */
  public class ThirdThread implements Callable<Integer>{

    private int ticket = 20;

    @Override
    public Integer call(){

      for ( int i = 0;i<10;i++) {
        //獲取當(dāng)前的線程,只能用 Thread.currentThread() 獲取當(dāng)前的線程名
//        Log.d(TAG,Thread.currentThread().getName()+" "+i);

        if(this.ticket>0){
          Log.e(TAG, Thread.currentThread().getName() + ", 賣票:ticket=" + ticket--);
        }
      }


      return ticket;
    }
  }

  private void starCallableThread(){
    ThirdThread thirdThread = new ThirdThread();
    FutureTask<Integer> task = new FutureTask<Integer>(thirdThread);

    new Thread(task,"有返回值的線程").start();

    try {
      Integer integer = task.get();
      Log.d(TAG,"starCallableThread, 子線程的返回值="+integer);

    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }

  }

運行結(jié)果:

這里寫圖片描述

注意:Callable的call() 方法允許聲明拋出異常,并且允許帶有返回值。
程序最后調(diào)用FutureTask 對象的get()方法來返回Call()方法的返回值,導(dǎo)致主線程被阻塞,直到call()方法結(jié)束并返回為止。

4.三種方式的對比

采用繼承Thread 類的方式創(chuàng)建多線程

劣勢: 已經(jīng)繼承Thread類不能再繼承其他父類。

優(yōu)勢: 編寫簡單

采用繼承Runnable,Callable 接口的方式創(chuàng)建多線程

劣勢: 編程稍微有點復(fù)雜,如果需要訪問當(dāng)前線程必須使用Thread.currentThread()

優(yōu)勢:

(1)還可以繼承其他類
(2)多個線程可以共享一個target 對象,所以非常適合多個相同的線程來處理同一份資源的情況,從而將cpu,代碼和數(shù)據(jù)分開,形成清晰的模型,較好的體現(xiàn)類面向?qū)ο蟮乃枷搿?/p>

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • springboot單獨在指定地方輸出sql的方法

    springboot單獨在指定地方輸出sql的方法

    一般線上項目都是將日志進(jìn)行關(guān)閉,因為mybatis日志打印,時間長了,會占用大量的內(nèi)存,如果我想在我指定的地方進(jìn)行打印sql情況,本文就給大家介紹了springboot單獨在指定地方輸出sql的方法,需要的朋友可以參考下
    2023-10-10
  • Java打包之后讀取Resources下的文件失效原因及解決方法

    Java打包之后讀取Resources下的文件失效原因及解決方法

    這篇文章主要給大家介紹了Java打包之后讀取Resources下的文件失效的問題分析和解決方法,文中通過代碼示例和圖文結(jié)合給大家講解非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 深入淺析HashMap key和value能否為null

    深入淺析HashMap key和value能否為null

    HashMap的key和value可為null,線程不安全,HashTable的key和value均不可為null,線程安全,ConcurrentHashMap在多線程場景下使用,key和value也不能為null,還對它們進(jìn)行了測試和底層代碼分析,本文介紹HashMap key和value能否為null,感興趣的朋友跟隨小編一起看看吧
    2025-04-04
  • 解決SpringBoot加載application.properties配置文件的坑

    解決SpringBoot加載application.properties配置文件的坑

    這篇文章主要介紹了SpringBoot加載application.properties配置文件的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Jdk中沒有jre文件夾怎么辦?如何解決?

    Jdk中沒有jre文件夾怎么辦?如何解決?

    這篇文章主要介紹了Jdk中沒有jre文件夾怎么辦?如何解決的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Spring集成Web環(huán)境與SpringMVC組件的擴展使用詳解

    Spring集成Web環(huán)境與SpringMVC組件的擴展使用詳解

    這篇文章主要介紹了Spring集成Web環(huán)境與SpringMVC組件,它是一個MVC架構(gòu),用來簡化基于MVC架構(gòu)的Web應(yīng)用開發(fā)。SpringMVC最重要的就是五大組件
    2022-08-08
  • mybatis查詢匹配機制圖文詳解

    mybatis查詢匹配機制圖文詳解

    這篇文章主要給大家介紹了關(guān)于mybatis查詢匹配機制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Spring配置文件如何使用${username}

    Spring配置文件如何使用${username}

    這篇文章主要介紹了Spring配置文件如何使用${username},文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 淺談springboot多模塊(modules)開發(fā)

    淺談springboot多模塊(modules)開發(fā)

    這篇文章主要介紹了淺談springboot多模塊(modules)開發(fā),詳細(xì)的介紹了springboot多模塊的實現(xiàn),有興趣的可以了解一下
    2017-09-09
  • java實現(xiàn)在線預(yù)覽--poi實現(xiàn)word、excel、ppt轉(zhuǎn)html的方法

    java實現(xiàn)在線預(yù)覽--poi實現(xiàn)word、excel、ppt轉(zhuǎn)html的方法

    這篇文章主要介紹了java實現(xiàn)在線預(yù)覽--poi實現(xiàn)word、excel、ppt轉(zhuǎn)html的方法,本文需要引入poi的jar包給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2019-09-09

最新評論