一. 创建线程方式
1.无返回值
1.实现Runnable接口,重新run()
例如:
class FirstThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("First- Thread:" + i);
}
}
}
最后:Thread ft = new Thread(new FirstThread());
ft.start();
例如:
Runnable producer = () -> produceData(pos);
public static void produceData(PipedOutputStream pos) {
try {
for (int i = 1; i <= 50; i++) {
pos.write((byte) i);
pos.flush();
System.out.println("Writing: " + i);
Thread.sleep(500);
}
pos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
最后: new Thread(producer).start();
2.继承Thread类
static class SecondThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("First- Thread:" + i);
}
}
}
Thread ft2 = new Thread(new SecondThread());
ft.start();
这两种方式缺陷,在执行完任务之后无法获取执行结果。
2.有返回值
1.callable接口实现
static class ThirdThread implements Callable<Integer> {
private static Integer value = 0;
@Override
public Integer call() throws Exception {
System.out.println("执行call方法之前 value = " + value);
value = value.intValue() + 1;
System.out.println("执行call方法之后 value = " + value);
return value;
}
}
FutureTask<Integer> task = new FutureTask<Integer>(new ThirdThread());
Thread thread = new Thread(task);
thread.start();
System.out.println("task.get() returns " + task.get());
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> result = executor.submit(new ThirdThread());
executor.shutdown();
重写call,创建FutureTask的对象,其中FutureTask定义了run接口,run()内部调用了call的返回值,并保存了call()的返回值,其中Interger就是返回值类型。
二.Future
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
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;
}
Future 提供的功能
1)判断任务是否完成;
2)能够中断任务;
3)能够获取任务执行结果。
三.FutureTask
public class FutureTask<V> implements RunnableFuture<V>
FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
事实上,FutureTask是Future接口的一个唯一实现类。
四.ListenableFuture 与 CompletableFuture
老版Future模式一个最大的问题是需要获取结果做后续处理操作的时候,还是需要阻塞等待。这样的话,和同步调用方式就没有多大区别了。
按照先后顺序来讲的话,首先是ListenableFuture,这是由Google Guava工具包提供的Future扩展类,随后,JDK在1.8版本中马上也提供了类似这样的类,就是CompletableFuture。
4.1 ListenableFuture
最大的区别与Future做到了一个可以监听结果的Future。
ListenableFuture<?> listenableFuture = executorService.submit(new MyCallable(3, 10));
//使用监听的方式
listenableFuture.addListener(() -> {
System.out.println("listen success");
}, executorService);
// FutureCallback接口包含onSuccess()、onFailure()两个方法
Futures.addCallback(listenableFuture, new FutureCallback<Object>() {
@Override
public void onSuccess(@Nullable Object result) {
System.out.println("res: " + result);
}
@Override
public void onFailure(Throwable t) {
}
}, executorService);
class MyCallable implements Callable<Integer> {
private int a;
private int b;
public MyCallable(int a, int b) {
this.a = a;
this.b = b;
}
@Override
public Integer call() throws Exception {
return a * b;
}
}
4.2 CompletableFuture
CompletableFuture增加了六种类似Future的新方法。
join()和getNow(value)。 第一个,join(),阻塞直到CompletableFuture完成,和Future的get()方法一样。 主要区别在于join() 方法不会抛出显式的异常(get()方法抛出InterruptedException, ExecutionException异常),从而更简单
complete(value)方法完成CompletableFuture(如果CompletableFuture没有结束),并返回value。
模式选择
一对一模式
从第一个CompletableFuture开始,当完成其任务执行时,我们创建的第二个CompletableFuture开始执行。
4.2.1 CompletableFuture的静态工厂方法
方法名 | 描述 |
---|---|
runAsync(Runnable runnable) | 使用ForkJoinPool.commonPool()作为它的线程池执行异步代码。 |
runAsync(Runnable runnable, Executor executor) | 使用指定的thread pool执行异步代码。 |
supplyAsync(Supplier supplier) | 使用ForkJoinPool.commonPool()作为它的线程池执行异步代码,异步操作有返回值 |
supplyAsync(Supplier supplier, Executor executor) | 使用指定的thread pool执行异步代码,异步操作有返回值 |
4.2.2 Completable
方法名 | 描述 |
---|---|
complete(T t) | 完成异步执行,并返回future的结果 |
completeExceptionally(Throwable ex) | 异步执行不正常的结束 |
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
future.completeExceptionally(new Exception());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
4.2.3 map
方法名 | header 2 |
---|---|
thenApply(Function<? super T,? extends U> fn) | 接受一个Function<? super T,? extends U>参数用来转换CompletableFuture |
thenApplyAsync(Function<? super T,? extends U> fn) | 接受一个Function<? super T,? extends U>参数用来转换CompletableFuture,使用ForkJoinPool |
thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) | 接受一个Function<? super T,? extends U>参数用来转换CompletableFuture,使用指定的线程池 |
4.2.4 flatMap
方法名 | 描述 |
---|---|
thenCompose(Function<? super T, ? extends CompletionStage> fn) | 在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。 |
thenComposeAsync(Function<? super T, ? extends CompletionStage> fn) | 在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。使用ForkJoinPool。 |
thenComposeAsync(Function<? super T, ? extends CompletionStage> fn,Executor executor) | 在异步操作完成的时候对异步操作的结果进行一些操作,并且仍然返回CompletableFuture类型。使用指定的线程池。 |
thenCompose,将前一个结果作为下一个计算的参数,它们之间存在着先后顺序。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
4.2.5 组合
方法名 | 描述 |
---|---|
thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) | 当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。 |
thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) | 当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。使用ForkJoinPool。 |
thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor) | 当两个CompletableFuture都正常完成后,执行提供的fn,用它来组合另外一个CompletableFuture的结果。使用指定的线程池。 |
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "100");
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 100);
CompletableFuture<Double> future = future1.thenCombine(future2, (s, i) -> Double.parseDouble(s + i));
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
附录:函数式编程
name | type | description |
---|---|---|
Consumer | Consumer< T > | 接收T对象,不返回值 |
Predicate | Predicate< T > | 接收T对象并返回boolean |
Function | Function< T, R > | 接收T对象,返回R对象 |
Supplier | Supplier< T > | 提供T对象(例如工厂),不接收值 |
UnaryOperator | UnaryOperator | 接收T对象,返回T对象 |
BinaryOperator | BinaryOperator | 接收两个T对象,返回T对象 |
接口
Function<T, R>
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}