CompletableFuture
概要
CompletableFuture类简介
官网API地址
public class CompletableFuture implements Future, CompletionStage 】
CompletableFuture是Java 8中新增的一个用以异步处理的一个类,它实现了Future接口,对Future的功能进行了扩展。
get()、get(long timeout,TimeUnit unit)和getNow(T valueIfAbsent)
get()、get(long timeout,TimeUnit unit): 调用这两个方法都会阻塞当前线程,直到结束任务或者手动调用结束方法complete(T value)、completeExceptionally(Throwable ex)。不同的是,第二个方法可以指定超时时间,如果在指定时间内未完成任务,将会抛出 java.util.concurrent.TimeoutException异常。
getNow(T valueIfAbsent): 如果任务已完成,则返回结果;否则返回给定的默认值。注意该方法的调用不会导致阻塞。
示例:
package Main;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Main {
private static CompletableFuture<String> future;
public static void main(String[] args) throws ExecutionException {
future = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("run end");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "completable";
});
try {
future.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* try { future.get(3, TimeUnit.SECONDS); } catch (InterruptedException |
* TimeoutException e) { // TODO Auto-generated catch block e.printStackTrace();
* }
*/// java.util.concurrent.TimeoutException
// Returns the result value (or throws any encountered exception) if completed,
// else returns the given valueIfAbsent.
System.out.println(future.getNow("default value"));
System.out.println("end");
}
}
runAsync(Runnable)和runAsync(Runnable,Executor)
runAsync接受的是Runnable对象,所以不存在返回值。
runAsync(Runnable):
返回一个新的CompletableFuture,它在运行给定操作后由ForkJoinPool.commonPool()中运行的任务异步完成。
package Main;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class RunAsync {
public static void main(String[] args) {
//Returns a new CompletableFuture that is asynchronously completed
//by a task running in the ForkJoinPool.commonPool() after it runs the given action.
CompletableFuture future = CompletableFuture.runAsync(() -> {
System.out.println("run");
});
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
runAsync(Runnable,Executor):
返回一个新的CompletableFuture,它运行在给定的线程池中。
package Main;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunAsync {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
CompletableFuture future = CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
System.out.println("run");
}
}, exec);
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
supplyAsync(Supplier)和supplyAsync(Supplier,Executor)
supplyAsync(Supplier)
package Main;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class SupplyAsync {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("supplyAsync");
return "return value";
});
try {
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
supplyAsync(Supplier,Executor)
package Main;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SupplyAsync {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("supplyAsync");
return "return value";
}, exec);
try {
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
thenApply 和 handle
如果两个任务之间有依赖关系,比如B任务依赖于A任务的执行结果,那么就可以使用这两个方法.
这两个方法,效果是一样的,区别在于,当A任务执行出现异常时,thenApply方法不会执行,而handle 方法一样会去执行,因为在handle方法里,我们可以处理异常,而前者不行。
package Main;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Main {
private static CompletableFuture<Integer> future;
public static void main(String[] args) throws ExecutionException {
future = CompletableFuture.supplyAsync(() -> {
return 5;
}).thenApply((r) -> {
r = r + 1;
return r;
});
try {
System.out.println(future.get());
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 出现了异常,handle方法可以拿到异常 e
future.supplyAsync(() -> {
int i = 10 / 0;
return 5;
}).handle((r, e) -> {
System.out.println(e);
r = r + 1;
return r;
});
}
}
thenCombine 和 thenAcceptBoth
我们常常需要合并两个任务的结果,在对其进行统一处理,简言之,这里的回调任务需要等待两个任务都完成后再会触发。这两者的区别 在于 前者是有返回值的,后者没有(就是个消耗工作)
package Main;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Main {
public static void main(String[] args) throws ExecutionException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "future1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
return "future2";
});
CompletableFuture<String> result = future1.thenCombine(future2, (r1, r2) -> {
return r1 + r2;
});
try {
System.out.println(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}