java Future FutureTask 並行作業

來源:互聯網
上載者:User

標籤:

1.1 綜述

    建立線程有兩種方式:extends Thread || inplements Runable,但是這兩種方式都有一個缺陷,就是執行完任務後不能擷取執行結果。

    如果非要擷取到執行結果的話,就必須通過共用變數或者是線程通訊的方法來達到效果,使用較為麻煩,為瞭解決這種問題,java提供了Callable Future ,通過他們可以再任務執行完畢後得到任務執行結果。

1.2 Runable Callable 對比

java.lang.Runable是一個介面,聲明了run()方法:

public interface Runable {    public abstract void run();}
因為run()方法傳回值void,所以執行完任務後不能返回結果。
java.util,concurrent.Callable 也是一個介面,裡面聲明了一個方法call();    
public interface Callable<V> {    V call() throws Exception;}
call{}函數返回的類型就是這個傳遞進來的V類型,使用Callable 就需要配合ExecutorService配合使用:
<T> Future<T> submit(Callable<T> task);<T> Future<T> submit(Runnable task, T result);Future<?> submit(Runnable task);



1.3 Future 介面 方法含義

Future類位於java.util.concurrent包下,它是一個介面

public interface Future<V> {    boolean cancel(boolean mayInterruptIfRunning);    boolean isCancelled();    boolean isDone();    V get()           throws InterruptedException, ExecutionException;    V get(long timeout, TimeUnit unit)          throws InterruptedException, ExecutionException, TimeoutException;}



cancel方法用來取消任務,如果取消任務成功則返回true,如果取消任務失敗則返回false。參數mayInterruptIfRunning表示是否允許取消正在執行卻沒有執行完畢的任務,如果設定true,則表示可以取消正在執行過程中的任務。如果任務已經完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經完成的任務會返回false;如果任務正在執行,若mayInterruptIfRunning設定為true,則返回true,若mayInterruptIfRunning設定為false,則返回false;如果任務還沒有執行,則無論mayInterruptIfRunning為true還是false,肯定返回true。
          isCancelled方法表示任務是否被取消成功,如果在任務正常完成前被取消成功,則返回 true。
           isDone方法表示任務是否已經完成,若任務完成,則返回true;
          get()方法用來擷取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;
          get(long timeout, TimeUnit unit)用來擷取執行結果,如果在指定時間內,還沒擷取到結果,就直接返回null。

1.4 Future FutureTask 相關

因為Future只是一個介面,所以是無法直接用來建立對象使用的,因此就有了下面的FutureTask。
FutureTask是Future介面的一個唯一實作類別。

public class FutureTask<V> implements RunnableFuture<V>          public interface RunnableFuture<V> extends Runnable, Future<V> {    void run();}



FutureTask提供了2個構造器:
public FutureTask(Callable<V> callable) {}public FutureTask(Runnable runnable, V result) {}



1.5 程式碼範例

樣本

package com.test.java.future;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class Test {        public static void main(String[] args) {              ExecutorService executor = Executors. newCachedThreadPool();              Task task = new Task();              Future<Integer> result = executor.submit(task);              executor.shutdown();               try {                     Thread. sleep(1000);              } catch (InterruptedException e1) {                     e1.printStackTrace();              }              System. out.println("主線程在執行任務" );               try {                     System. out.println("task運行結果" + result.get());              } catch (InterruptedException e) {                     e.printStackTrace();              } catch (ExecutionException e) {                     e.printStackTrace();              }              System. out.println("所有任務執行完畢" );       }}class Task implements Callable<Integer> {        @Override        public Integer call() throws Exception {              System. out.println("子線程在進行計算" );              Thread. sleep(3000);               int sum = 0;               for (int i = 0; i < 100; i++)                     sum += i;               return sum;       }}package com.test.java.future;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.FutureTask;public class Test1 {        public static void main(String[] args) {               // 第一種方式              ExecutorService executor = Executors. newCachedThreadPool();              Task1 task = new Task1();              FutureTask<Integer> futureTask = new FutureTask<Integer>(task);              executor.submit(futureTask);              executor.shutdown();               // 第二種方式,注意這種方式和第一種方式效果是類似的,只不過一個使用的是ExecutorService,一個使用的是Thread               /*               * Task task = new Task(); FutureTask<Integer> futureTask = new               * FutureTask<Integer>(task); Thread thread = new Thread(futureTask);               * thread.start();               */               try {                     Thread. sleep(1000);              } catch (InterruptedException e1) {                     e1.printStackTrace();              }              System. out.println("主線程在執行任務" );               try {                     System. out.println("task運行結果" + futureTask.get());              } catch (InterruptedException e) {                     e.printStackTrace();              } catch (ExecutionException e) {                     e.printStackTrace();              }              System. out.println("所有任務執行完畢" );       }}class Task1 implements Callable<Integer> {        @Override        public Integer call() throws Exception {              System. out.println("子線程在進行計算" );              Thread. sleep(3000);               int sum = 0;               for (int i = 0; i < 100; i++)                     sum += i;               return sum;       }}



1.6 另外一個恰當的樣本說明

舉個簡單的例子:當你在網上購物時,如果付款成功了,你是否立即拿到了你買到的商品?當然不是,當你付款成功時,你得到的僅僅是一個,訂單提交成功的提示而已,其它的什麼都沒了,從這一刻開始,你是否會一直呆在家裡,什麼都不做,直到你的商品送到你手中呢?當然也不是,當你訂單提交成功後,你會去做你該做的,當你的商品送到時,你只需簽收一下即可,從訂單提交到商品送到之間,你不會因為等待商品送到而耽誤你的時間,你可以自由支配你的時間,好像什麼都沒有發生一樣。
是的,Future模式就是這個意思
當客戶提交一個請求時,這個請求有可能會花很長一段時間去處理後台資料,之後,再返回給客戶一個處理過的資料,那這段時間,客戶一直在等待服務端的響應,是不是會讓客戶覺得很厭煩呢?當然會了,所以Future模式就是為了提高回應時間而誕生的,當然這個提高其實是一個假象。當客戶提交一個請求時,我們讓客戶立即返回一個虛擬資料響應,之後,用戶端就不用為了等待響應而無事可做了,此後,用戶端可以進行別的任何操作,當真正的資料處理完返回給客戶了,客戶再去進行相應的處理,這樣就會讓客戶沒有無謂的等待了.

package com.test.java.future;import java.util.concurrent.Callable;public class MyData implements Callable<String> {        private String myStr ;               public MyData(String myStr) {               this .myStr = myStr;       }               @Override        public String call() throws Exception {              StringBuffer sb = new StringBuffer();               for (int i=0;i<10;i++) {                     sb.append( myStr);                      try {                           Thread. sleep(1000);                     } catch (Exception e) {                           e.printStackTrace();                     }              }               return sb.toString();       }}
 
package com.test.java.future;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.FutureTask;public class MyDataTest {               public static void main(String[] args) {              FutureTask<String> future = new FutureTask<String>( newMyData("alexgaoyh" ));              ExecutorService exe = Executors. newFixedThreadPool(1);              exe.submit(future);              exe.shutdown();              System. out .println("用戶端請求結束了" );              System. out .println("任務是否已經完成:" +future.isDone());               try {                      /*                      * 這段時間,就是後台在擷取真正資料的時間                      */                     System. out .println("在這段時間,我可以做我自己的事情" );                     System. out .println("真正的資料:" +future.get());                     System. out .println("任務是否已經完成:" +future.isDone());              } catch (Exception e) {                     e.printStackTrace();              }       }       }



java Future FutureTask 並行作業

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.