2017-04-09 325 views
0

我想在Java8中探索CompletableFuture,我寫了這個簡單的例子來消費假api,但我得到這個編譯錯誤,我添加了圍繞那段代碼的try/catch塊,但是我我仍然收到相同的編譯錯誤。CompletableFuture:未處理的異常類型ExecutionException

* FakeAPI1 *

package com.fake.api; 

public class FakeAPI1 implements FakeAPI{ 

    @Override 
    public void consume(){ 
     try{ 
      Thread.sleep(1000L); 
      System.out.println("Hello from FakeAPI1"); 
     }catch(InterruptedException e){ 
      System.out.println("Eat it silently"); 
     } 
    } 

    public String getRandomText(){ 
     System.out.println("getRandomText() @ FakeAPI1 was called "); 
     try{ 
      Thread.sleep(1000L); 
      return "Hello from FakeAPI1"; 
     }catch(InterruptedException e){ 
      System.out.println("Eat it silently"); 
     } 
     return "Default message from FakeAPI1"; 
    } 
} 

* CompletableFutureTest *

package com.example.completablefuture; 

import java.util.Arrays; 
import java.util.List; 
import java.util.concurrent.CompletableFuture; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.Future; 
import java.util.stream.Collectors; 

import com.fake.api.FakeAPI1; 

public class CompletableFutureTest { 

    public static void main(String[] args) 
      throws InterruptedException,ExecutionException { 

     List<Future<FakeAPI1>> apis= 
       Arrays.asList(
        new CompletableFuture<FakeAPI1>(), 
        new CompletableFuture<FakeAPI1>(), 
        new CompletableFuture<FakeAPI1>() 
       ); 

     Long start= System.currentTimeMillis(); 
      apis.stream() 
       //Compilation error is in the line below 
       //Unhandled exception type ExecutionException 
       .map(api->api.get().getRandomText()) 
       .collect(Collectors.toList()); 


     Long end= System.currentTimeMillis(); 
     System.out.println("CompletableFutureTest took " + (end-start) + " ms"); 

    } 

} 

我在下面的答案添加try/catch塊按照建議,編譯錯誤不再顯示但是當我運行代碼時它什麼也不做,看起來好像是在等待什麼......

package com.example.completablefuture; 

import java.util.Arrays; 
import java.util.List; 
import java.util.concurrent.CompletableFuture; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.Future; 
import java.util.stream.Collectors; 

import com.fake.api.FakeAPI1; 

public class CompletableFutureTest { 

public static void main(String[] args) 
     throws InterruptedException,ExecutionException { 

    List<CompletableFuture<FakeAPI1>> apis= 
      Arrays.asList(
       new CompletableFuture<FakeAPI1>(), 
       new CompletableFuture<FakeAPI1>(), 
       new CompletableFuture<FakeAPI1>() 
      ); 

    Long start= System.currentTimeMillis(); 
    List<String> result= apis.stream() 
     .map(api-> { 
      try { 
       System.out.println("1"); 
       api.get().getRandomText(); 
      }catch (ExecutionException e) { 
       // TODO: return something else or throw a runtime exception 
       System.out.println("ExecutionException"); 
      }catch(InterruptedException e){ 
       // TODO: return something else or throw a runtime exception 
       System.out.println("InterruptedException"); 
      } 
      return "NA"; 
     }) 
     .collect(Collectors.toList()); 

    result.stream() 
      .forEach(System.out::println); 

    Long end= System.currentTimeMillis(); 
    System.out.println("CompletableFutureTest took " + (end-start) + " ms"); 

} 

} 

我添加了一個超時參數給get()方法,並開始投擲InterruptedException的

package com.example.completablefuture; 

    import java.util.Arrays; 
    import java.util.List; 
    import java.util.concurrent.CompletableFuture; 
    import java.util.concurrent.ExecutionException; 
    import java.util.concurrent.Future; 
    import java.util.concurrent.TimeUnit; 
    import java.util.concurrent.TimeoutException; 
    import java.util.stream.Collectors; 


    import com.fake.api.FakeAPI1; 

public class CompletableFutureTest { 

public static void main(String[] args) 
     throws InterruptedException,ExecutionException { 

    List<CompletableFuture<FakeAPI1>> apis= 
      Arrays.asList(
       new CompletableFuture<FakeAPI1>(), 
       new CompletableFuture<FakeAPI1>(), 
       new CompletableFuture<FakeAPI1>() 
      ); 

    Long start= System.currentTimeMillis(); 
    List<String> result= apis.stream() 
     .map(api-> { 
      try { 
       System.out.println("about to call get() method ..."); 
       api.get(1000L, TimeUnit.MILLISECONDS).getRandomText(); 
      }catch (ExecutionException e) { 
       // TODO: return something else or throw a runtime exception 
       System.out.println("ExecutionException"); 
      }catch(InterruptedException e){ 
       // TODO: return something else or throw a runtime exception 
       System.out.println("InterruptedException"); 
      }catch(TimeoutException e){ 
       // TODO: return something else or throw a runtime exception 
       System.out.println("InterruptedException"); 
      } 
      return "NA"; 
     }) 
     .collect(Collectors.toList()); 

    result.stream() 
      .forEach(System.out::println); 

    Long end= System.currentTimeMillis(); 
    System.out.println("CompletableFutureTest took " + (end-start) + " ms"); 

} 
} 

about to call get() method ... 
InterruptedException 
about to call get() method ... 
InterruptedException 
about to call get() method ... 
InterruptedException 
NA 
NA 
NA 
CompletableFutureTest took 3062 ms 
+0

未處理的異常類型ExecutionException –

+0

這是一個編譯錯誤,不是一個異常 –

回答

2

你不要再追在正確的地方除外。 map()預計Function。而函數不能拋出任何檢查的異常。因此,你需要

.map(api-> { 
    try { 
     return api.get().getRandomText()); 
    } 
    catch (ExecutionException e) { 
     // TODO: return something else or throw a runtime exception 
    } 
}) 
+0

我按照你的建議添加了try/catch打擊,但它給了我這個編譯錯誤:這個方法必須返回Object類型的結果。我在catch塊之後添加了一個return語句,但是我又得到了相同的編譯錯誤。 –

+0

很難解釋爲什麼你的代碼在沒有看到你的代碼的情況下有問題。你必須返回**的東西**。不只是回來。 –

+0

我爲帖子添加了截圖^^ –

1

當使用CompletableFuture,你應該使用join()方法,而不是get()。它們在功能上是相同的(在非例外情​​況下),但前者不會拋出檢查的異常。