天天看點

java.util.concurrent之future

一、概述:

Future用來擷取異步執行的結果。隻要一個方法傳回一個future,那麼他就是一個異步方法;如下Junit方法,執行test,列印"我是test方法",過了10秒以後,列印Hello world;說明invoke 就是一個異步方法;

@Test
    public void test() {
        Future<String> future = invoke();
        System.out.println("我是test方法");
        try {
            String str = future.get();
            System.out.println(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Future<String> invoke() {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        Future<String> future = executorService.submit(() -> {
            // ...
            Thread.sleep(10000l);
            return "Hello world";
        });
        return future;

    }      

二、future 接口方法說明:

1.future接口:

java.util.concurrent之future
java.util.concurrent之future
1 package java.util.concurrent;
  2 
  3 /**
  4  * A {@code Future} represents the result of an asynchronous
  5  * computation.  Methods are provided to check if the computation is
  6  * complete, to wait for its completion, and to retrieve the result of
  7  * the computation.  The result can only be retrieved using method
  8  * {@code get} when the computation has completed, blocking if
  9  * necessary until it is ready.  Cancellation is performed by the
 10  * {@code cancel} method.  Additional methods are provided to
 11  * determine if the task completed normally or was cancelled. Once a
 12  * computation has completed, the computation cannot be cancelled.
 13  * If you would like to use a {@code Future} for the sake
 14  * of cancellability but not provide a usable result, you can
 15  * declare types of the form {@code Future<?>} and
 16  * return {@code null} as a result of the underlying task.
 17  *
 18  * <p>
 19  * <b>Sample Usage</b> (Note that the following classes are all
 20  * made-up.)
 21  * <pre> {@code
 22  * interface ArchiveSearcher { String search(String target); }
 23  * class App {
 24  *   ExecutorService executor = ...
 25  *   ArchiveSearcher searcher = ...
 26  *   void showSearch(final String target)
 27  *       throws InterruptedException {
 28  *     Future<String> future
 29  *       = executor.submit(new Callable<String>() {
 30  *         public String call() {
 31  *             return searcher.search(target);
 32  *         }});
 33  *     displayOtherThings(); // do other things while searching
 34  *     try {
 35  *       displayText(future.get()); // use future
 36  *     } catch (ExecutionException ex) { cleanup(); return; }
 37  *   }
 38  * }}</pre>
 39  *
 40  * The {@link FutureTask} class is an implementation of {@code Future} that
 41  * implements {@code Runnable}, and so may be executed by an {@code Executor}.
 42  * For example, the above construction with {@code submit} could be replaced by:
 43  *  <pre> {@code
 44  * FutureTask<String> future =
 45  *   new FutureTask<String>(new Callable<String>() {
 46  *     public String call() {
 47  *       return searcher.search(target);
 48  *   }});
 49  * executor.execute(future);}</pre>
 50  *
 51  * <p>Memory consistency effects: Actions taken by the asynchronous computation
 52  * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
 53  * actions following the corresponding {@code Future.get()} in another thread.
 54  *
 55  * @see FutureTask
 56  * @see Executor
 57  * @since 1.5
 58  * @author Doug Lea
 59  * @param <V> The result type returned by this Future's {@code get} method
 60  */
 61 public interface Future<V> {
 62 
 63     /**
 64      * Attempts to cancel execution of this task.  This attempt will
 65      * fail if the task has already completed, has already been cancelled,
 66      * or could not be cancelled for some other reason. If successful,
 67      * and this task has not started when {@code cancel} is called,
 68      * this task should never run.  If the task has already started,
 69      * then the {@code mayInterruptIfRunning} parameter determines
 70      * whether the thread executing this task should be interrupted in
 71      * an attempt to stop the task.
 72      *
 73      * <p>After this method returns, subsequent calls to {@link #isDone} will
 74      * always return {@code true}.  Subsequent calls to {@link #isCancelled}
 75      * will always return {@code true} if this method returned {@code true}.
 76      *
 77      * @param mayInterruptIfRunning {@code true} if the thread executing this
 78      * task should be interrupted; otherwise, in-progress tasks are allowed
 79      * to complete
 80      * @return {@code false} if the task could not be cancelled,
 81      * typically because it has already completed normally;
 82      * {@code true} otherwise
 83      */
 84     boolean cancel(boolean mayInterruptIfRunning);
 85 
 86     /**
 87      * Returns {@code true} if this task was cancelled before it completed
 88      * normally.
 89      *
 90      * @return {@code true} if this task was cancelled before it completed
 91      */
 92     boolean isCancelled();
 93 
 94     /**
 95      * Returns {@code true} if this task completed.
 96      *
 97      * Completion may be due to normal termination, an exception, or
 98      * cancellation -- in all of these cases, this method will return
 99      * {@code true}.
100      *
101      * @return {@code true} if this task completed
102      */
103     boolean isDone();
104 
105     /**
106      * Waits if necessary for the computation to complete, and then
107      * retrieves its result.
108      *
109      * @return the computed result
110      * @throws CancellationException if the computation was cancelled
111      * @throws ExecutionException if the computation threw an
112      * exception
113      * @throws InterruptedException if the current thread was interrupted
114      * while waiting
115      */
116     V get() throws InterruptedException, ExecutionException;
117 
118     /**
119      * Waits if necessary for at most the given time for the computation
120      * to complete, and then retrieves its result, if available.
121      *
122      * @param timeout the maximum time to wait
123      * @param unit the time unit of the timeout argument
124      * @return the computed result
125      * @throws CancellationException if the computation was cancelled
126      * @throws ExecutionException if the computation threw an
127      * exception
128      * @throws InterruptedException if the current thread was interrupted
129      * while waiting
130      * @throws TimeoutException if the wait timed out
131      */
132     V get(long timeout, TimeUnit unit)
133         throws InterruptedException, ExecutionException, TimeoutException;
134      

View Code

2.cancel && isCancelled:

  • 假設觸發了一個任務,但由于某種原因,不再關心結果。 可以使用 Future.cancel(boolean) 告訴 executor 停止操作并中斷其底層線程。且該線程狀态為執行完成:
  • isCancelled,可以判斷線程是否被取消;該方法為同步方法,即調用該方法立即傳回一個結果;

如下代碼,則結果是:

是否取消:true

java.util.concurrent.CancellationException...異常

該異常是以為線程已經取消,結果中沒有值導緻異常;

1     @Test
 2     public void test1() {
 3         Future<String> future = invoke();
 4         future.cancel(true);
 5         System.out.println("是否取消:" + future.isCancelled());
 6         try {
 7             String str = future.get();
 8             System.out.println(str);
 9         } catch (Exception e) {
10             e.printStackTrace();
11         }
12      

如果取消放在執行future完成後面,則無法取消;如下代碼運作結果:

Hello world

是否取消:false

1     @Test
 2     public void test() {
 3         Future<String> future = invoke();
 4         try {
 5             String str = future.get();
 6             System.out.println(str);
 7         } catch (Exception e) {
 8             e.printStackTrace();
 9         }
10         future.cancel(true);
11         System.out.println("是否取消:" + future.isCancelled());
12      

3.get & isDone

isDone:判斷該方法是否執行完成,該方法為同步的,也就是說調用該方法時,立即傳回一個結果;

get() 方法是阻塞的,也就是說,執行future.get(),該條語句需要等待future方法執行結束才能再往下執行;

get(long,TimeUnit)方法也是阻塞的,超過指定的時間,将會報TimeoutException。也就是說,他隻等future方法 timeout 秒時間,超過這個時間,future方法還想執行結束就報錯;

1 @Test
 2     public void test() {
 3         Future<String> future = invoke();
 4         System.out.println("是否執行完成:" + future.isDone());
 5         try {
 6             // String str = future.get(100, TimeUnit.SECONDS);
 7             String str = future.get();
 8             System.out.println(str);
 9         } catch (Exception e) {
10             e.printStackTrace();
11         }
12         System.out.println("是否執行完成:" + future.isDone());
13      

上面代碼執行結果為:

是否執行完成:false

Hello world

是否執行完成:true

Hello world 和 上面列印的語句時間間隔了10s以上;

4.get(long,TimeUnit)例子說明:

1 @Test
 2     public void test() {
 3         Future<String> future = invoke();
 4         System.out.println("是否執行完成:" + future.isDone());
 5         try {
 6             String str = future.get(9, TimeUnit.SECONDS);
 7             System.out.println(str);
 8         } catch (Exception e) {
 9             e.printStackTrace();
10         }
11         System.out.println("是否執行完成:" + future.isDone());
12      

改代碼執行結果為:

是否執行完成:false

java.util.concurrent.TimeoutException...

是否執行完成:false