小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Android(Java)之多線程結(jié)果返回——Future 、FutureTask、Callable、Runnable

 波波七 2016-06-22

Android、Java中Runnable十分常見,在開新線程時,我們常用new Thread(Runnable).start() 或者線程池搭載Runnable。

日常使用,在不需要線程返回時,使用的十分順手。

在需要線程返回時,我們也有辦法搞定,比如外部變量控制流程、新增監(jiān)聽接口等。

有了以上理由,Callable就被冷落了。

其實Callable能讓你的實現(xiàn)以及代碼更簡單。本文就是以Callable為中心來介紹的。

一、Callable與Runnable

為什么Runnable用的人多,而Callable用的少?

1、Callable還沒出現(xiàn)前,大家用的都是Runnable;(Callable是JDK5出現(xiàn)的)

2、Runnable用法更簡單;

具體的區(qū)別如下:

1、結(jié)構(gòu)

Callable接口是帶有泛型的,Callable<T>。該泛型T,也是Callable返回值的類型;Callable接口需要實現(xiàn)的方法為call方法;

Runnable接口需要實現(xiàn)的方法為run方法;

2、使用

Callable一般配合線程池的submit方法以及FutureTask使用,Runnable一般是配合new Thread或者線程池使用;

3、返回

Callable有返回值,并且可以自定義返回值類型;Runnable不行;

4、控制

Callable配合FutureTask,可以通過Future來控制任務(wù)執(zhí)行、取消,查看任務(wù)是否完成等。Runnable也可以通過Future來實現(xiàn)以上功能,但方式不一樣。


二、Future以及FutureTask

Callable的價值,在Future上體現(xiàn)。

Future是一個接口,而FutureTask是Future接口的官方唯一實現(xiàn)類。

1、Future接口

Future以及其實現(xiàn)類,是用于搭載Runnable或者Callable,執(zhí)行任務(wù)、控制任務(wù)并能有效返回結(jié)果。

Future接口內(nèi)容如下(去了注釋):

  1. package java.util.concurrent;  
  2.   
  3.   
  4. public interface Future<V> {  
  5.      
  6.     boolean cancel(boolean mayInterruptIfRunning);  
  7.   
  8.     boolean isCancelled();  
  9.   
  10.     boolean isDone();  
  11.       
  12.     V get() throws InterruptedException, ExecutionException;   
  13.       
  14.     V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;  
  15.       
  16.     }  

其中,isCancelled用于判斷是否已取消任務(wù)、isDone用于判斷是否已完成任務(wù)。

cancel用于取消任務(wù),cancel的參數(shù)表示是否可以中斷正在執(zhí)行中的任務(wù)。參數(shù)解釋如下:

任務(wù)未開始:無論設(shè)置參數(shù)為true還是false,都返回true;

任務(wù)正在執(zhí)行,并未結(jié)束:參數(shù)設(shè)置為true,則返回true(成功取消),如果設(shè)置為false,則返回false(不允許中斷正在執(zhí)行的任務(wù));

任務(wù)已結(jié)束:無論設(shè)置參數(shù)為true還是false,都返回false;

get方法用于獲取任務(wù)執(zhí)行的結(jié)果,get方法是一個阻塞方法,會等到任務(wù)執(zhí)行完畢。

get(long timeout,TimeUnit unit)方法也是一個阻塞方法,等待任務(wù)執(zhí)行的結(jié)果,但它只等到超時時間結(jié)束,如果任務(wù)還未執(zhí)行完成,則返回一個null。

2、FutureTask類

FutureTask類不止實現(xiàn)了Future接口,還實現(xiàn)了其他的接口——Runnable,如下:

  1. public class FutureTask<V> implements RunnableFuture<V>  
  1. public interface RunnableFuture<V> extends Runnable, Future<V>  
因此,F(xiàn)utureTask其實也可以用于new Thread(FutureTask),當然也用于線程池。

FutureTask與Future接口相比,功能擴張了很多。

首先看它的構(gòu)造函數(shù):

  1. public FutureTask(Runnable runnable, V result)  
  1. public FutureTask(Callable<V> callable)  
看到這里,我們知道通過FutureTask,你可以傳入Callable或者Runnable,而FutureTask則搭載二者。最后,F(xiàn)utureTask會將自身作為新開線程或者線程池的參數(shù)。

FutureTask有一個很重要的方法,是Done(),用于表示該FutureTask中的任務(wù)已執(zhí)行完畢。后面會在代碼中介紹。


三、實例解析

有這么一個場景:

你需要順序的執(zhí)行一系列任務(wù),上一個任務(wù)是下一個任務(wù)的前置。下一個任務(wù)需要根據(jù)上一個任務(wù)的結(jié)果來判斷是否執(zhí)行。如果上一個任務(wù)失敗則不再往下執(zhí)行任務(wù)。

這些任務(wù)都是耗時的,你是在Android上執(zhí)行這些任務(wù)的。

出現(xiàn)這個場景,在JDK5前,你用Runnable以及外部變量控制,是可以實現(xiàn)的。在JDK5以后,我們嘗試用Callable配合FutureTask來實現(xiàn)。(Runnable配合Future也是可以的,只是不常用)。


根據(jù)場景,設(shè)計方案:

(1)串行線程池+Callable+FutureTask

(2)串行線程池+Runnable+FutureTask

(3)外部變量控制——不再演示

(4)全局監(jiān)聽——不再演示

這里演示的是1、2兩種方案。

這里貼上為以上場景寫的工具類和方法:

  1. package com.example.androidfuturecallabledemo;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6. import java.util.concurrent.FutureTask;  
  7.   
  8. public class FutureThreadPool {  
  9.   
  10.     private FutureThreadPool(){}  
  11.     private volatile static FutureThreadPool futureThreadPool;  
  12.     private static ExecutorService threadExecutor;  
  13.     /**  
  14.      * 獲取線程池實例(單例模式)  
  15.      * @return  
  16.      */  
  17.     public static FutureThreadPool getInstance(){  
  18.         if(futureThreadPool==null){  
  19.             synchronized (FutureThreadPool.class) {  
  20.                 futureThreadPool=new FutureThreadPool();  
  21.                 threadExecutor=Executors.newSingleThreadExecutor();  
  22.             }  
  23.         }  
  24.         return futureThreadPool;  
  25.     }  
  26.       
  27.       
  28.     /**  
  29.      * 線程池處理Runnable(無返回值)  
  30.      * @param runnable Runnable參數(shù)  
  31.      */  
  32.     public void executeTask(Runnable runnable){  
  33.         threadExecutor.execute(runnable);  
  34.     }  
  35.       
  36.     /**  
  37.      * 線程池處理Callable<T>,F(xiàn)utureTask<T>類型有返回值  
  38.      * @param callable Callable<T>參數(shù)  
  39.      * @return FutureTask<T>  
  40.      */  
  41.     public <T> FutureTask<T> executeTask(Callable<T> callable){  
  42.         FutureTask<T> futureTask= new FutureTask<T>(callable);  
  43.         threadExecutor.submit(futureTask);  
  44.         return futureTask;  
  45.           
  46.     }  
  47.     /**  
  48.      * 線程池處理Runnable,F(xiàn)utureTask<T>類型有返回值(該方法不常用)  
  49.      * @param Runnable參數(shù)  
  50.      * @param T Runnable任務(wù)執(zhí)行完成后,返回的標識(注意:在調(diào)用時傳入值,將在Runnable執(zhí)行完成后,原樣傳出)  
  51.      * @return FutureTask<T>  
  52.      */  
  53.     public <T> FutureTask<T> executeTask(Runnable runnable,T result){  
  54.         FutureTask<T> futureTask= new FutureTask<T>(runnable,result);  
  55.         threadExecutor.submit(futureTask);  
  56.         return futureTask;  
  57.     }  
  58.     /**  
  59.      * 線程池處理自定義SimpleFutureTask,任務(wù)結(jié)束時有onFinish事件返回提示  
  60.      * @param mFutureTask 自定義SimpleFutureTask  
  61.      */  
  62.     public  <T> FutureTask<T>  executeFutureTask(SimpleFutureTask<T> mFutureTask){  
  63.         threadExecutor.submit(mFutureTask);  
  64.         return mFutureTask;  
  65.     }  
  66.       
  67.       
  68. }  

  1. package com.example.androidfuturecallabledemo;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.FutureTask;  
  5. /**  
  6.  * 任務(wù)結(jié)束回調(diào)onFinish的添加  
  7.  * @author zhao.yang  
  8.  *  
  9.  * @param <T>  
  10.  */  
  11. public abstract class SimpleFutureTask<T> extends FutureTask<T>{  
  12.   
  13.     public SimpleFutureTask(Callable<T> callable) {  
  14.         super(callable);  
  15.     }  
  16.   
  17.     @Override  
  18.     protected void done() {  
  19.         onFinish();  
  20.     }  
  21.       
  22.     public abstract void onFinish();  
  23.   
  24.       
  25. }  

以上是創(chuàng)建的工具類,結(jié)合封裝了Callable/Runnable、FutureTask以及線程池,方便調(diào)用。這里特別注意executeFutureTask方法,在該方法中,重寫了done方法以及新增

onFinish抽象方法,可以通過回調(diào)onFinish,通知調(diào)用者任務(wù)執(zhí)行結(jié)束。調(diào)用者,也可以通過FutureTask的get方法來阻塞,直到任務(wù)結(jié)束。


最后,貼上調(diào)用代碼:

  1. package com.example.androidfuturecallabledemo;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.ExecutionException;  
  5. import java.util.concurrent.Future;  
  6. import java.util.concurrent.FutureTask;  
  7.   
  8. import android.app.Activity;  
  9. import android.os.Bundle;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.widget.Button;  
  13. import android.widget.TextView;  
  14.   
  15. public class MainActivity extends Activity {  
  16.   
  17.     Button btnButton;  
  18.     TextView txtTextView;  
  19.     @Override  
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_main);  
  23.         btnButton=(Button)findViewById(R.id.btn);  
  24.         txtTextView=(TextView)findViewById(R.id.txt);  
  25.           
  26.         btnButton.setOnClickListener(new OnClickListener() {  
  27.               
  28.             @Override  
  29.             public void onClick(View v) {  
  30.                 try {  
  31.                     doSomeThing();  
  32.                 } catch (InterruptedException e) {  
  33.                     e.printStackTrace();  
  34.                 } catch (ExecutionException e) {  
  35.                     e.printStackTrace();  
  36.                 }  
  37.             }  
  38.         });  
  39.     }  
  40.     private int i=0;  
  41.     public void doSomeThing() throws InterruptedException, ExecutionException{  
  42.         System.out.println("1 main thread ..."+" Thread id:"+Thread.currentThread().getId());  
  43.         //Runnable  
  44.         FutureThreadPool.getInstance().executeTask(new Runnable() {  
  45.               
  46.             @Override  
  47.             public void run() {  
  48.                 try {  
  49.                     Thread.sleep(3*1000);  
  50.                     System.out.println("2 Runnable in FutureTask ..."+" Thread id:"+Thread.currentThread().getId());  
  51.                 } catch (InterruptedException e) {  
  52.                     // TODO Auto-generated catch block  
  53.                     e.printStackTrace();  
  54.                 }  
  55.                   
  56.             }  
  57.         });  
  58.       
  59.         //Callable   
  60.         Future<String> futureTask= FutureThreadPool.getInstance().executeTask(new Callable<String>() {  
  61.               
  62.             @Override  
  63.             public String call() throws Exception {  
  64.                 Thread.sleep(3*1000);  
  65.                 return "callable back return";  
  66.             }  
  67.         });  
  68.          System.out.println("3 Callable in FutureTask ... Result:"+futureTask.get()+" Thread id:"+Thread.currentThread().getId());  
  69.           
  70.        //Runnable+T result  
  71.      FutureTask<Integer> futureTask2=FutureThreadPool.getInstance().executeTask(new Runnable() {  
  72.           
  73.         @Override  
  74.         public void run() {  
  75.                  i=7;             
  76.         }  
  77.     }, 9);  
  78.        
  79.      System.out.println("4 Callable and <T> in FutureTask ... Result:"+futureTask2.get()+" Thread id:"+Thread.currentThread().getId()+" i="+i);  
  80.   
  81.           
  82.          FutureThreadPool.getInstance().executeFutureTask(new myFutrueTask(new Callable<String>() {  
  83.   
  84.             @Override  
  85.             public String call() throws Exception {  
  86.                 // TODO Auto-generated method stub  
  87.                 String resu="5 SimpleFutureTask";  
  88.                  System.out.println("5 SimpleFutureTask ... Result:"+resu+" Thread id:"+Thread.currentThread().getId());  
  89.                 return resu;  
  90.             }  
  91.         }));  
  92.     }  
  93.       
  94.     class myFutrueTask extends SimpleFutureTask<String>{  
  95.   
  96.         public myFutrueTask(Callable<String> callable) {  
  97.             super(callable);  
  98.         }  
  99.   
  100.         @Override  
  101.         public void onFinish() {  
  102.              System.out.println("6 SimpleFutureTask ...Finish");  
  103.         }  
  104.           
  105.     }  
  106.   
  107. }  

運行,得到的結(jié)果如下:



注意點


在代碼運行過程中,有個地方十分需要注意,那就是FutureTask的其中一個重載方法:

  1. public FutureTask(Runnable runnable, V result)  
在代碼的調(diào)用中,我們傳入的是一個整形i,i最初復(fù)制為0,在任務(wù)中被賦值為7,但是在參數(shù)中,我們傳入的是9??创蛴〕鰜淼男畔⑽覀冎?,通過get方法,我們得到的值是9,而不是其他值。

看它在源碼中的調(diào)用:

  1. public FutureTask(Runnable runnable, V result) {  
  2.       this.callable = Executors.callable(runnable, result);  
  3.       this.state = NEW;       // ensure visibility of callable  
  4.   }  

  1. public static <T> Callable<T> callable(Runnable task, T result) {  
  2.        if (task == null)  
  3.            throw new NullPointerException();  
  4.        return new RunnableAdapter<T>(task, result);  
  5.    }  

  1. static final class RunnableAdapter<T> implements Callable<T> {  
  2.       final Runnable task;  
  3.       final T result;  
  4.       RunnableAdapter(Runnable task, T result) {  
  5.           this.task = task;  
  6.           this.result = result;  
  7.       }  
  8.       public T call() {  
  9.           task.run();  
  10.           return result;  
  11.       }  
  12.   }  

在第三段代碼中,你就懂的,這個T result,你傳入什么,在任務(wù)結(jié)束時,就傳回原值。

四、源碼

源碼地址:http://download.csdn.net/detail/yangzhaomuma/9554877




    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多