CompletableFuture:未处理的异常类型ExecutionException

时间:2017-04-09 16:52:08

标签: java

我正在尝试在Java8中探索CompletableFuture,我写了这个简单的例子来使用假的api但我得到了这个编译错误,我在这段代码周围添加了try / catch块但是我仍然得到相同的编译错误。

* 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()方法中添加了一个Timeout参数,并开始抛出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

2 个答案:

答案 0 :(得分:2)

您没有在正确的地方捕捉到异常。 map()需要Function。并且函数不能抛出任何已检查的异常。所以你需要

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

答案 1 :(得分:1)

使用CompletableFuture时,您应使用join()方法而不是get()。它们在功能上是相同的(在非特殊情况下),但前者不会抛出已检查的异常。