自從jdk1.5之後,java提供了一個比較強大的Future。主要用於解決執行時間比較長的任務。通常需要等待任務執行結束或者出錯才能返回結果。
接口定義
Future接口定義
package com.jiang.currents.future;
/**
* @Description 獲取計算呢結果和判斷任務是否完成兩個接口
* @createTime 2019年10月31日
*/
public interface Future<T> {
// 返回計算後的結果,該方法會陷入阻塞狀態
T get() throws InterruptedException ;
// 判斷任務是否已經被完成
boolean done();
}
FutureService接口定義
package com.jiang.currents.future;
/**
* @ClassName FutureService.java
* @Description FutureService主要用於提交任務
* @createTime 2019年10月31日
*/
public interface FutureService<IN,OUT> {
// 接受不需要返回值的任務,future.get()會獲得null
Future<?> submit(Runnable runnable);
// 提交需要返回值的任務,Task接口替代了Runnable接口
Future<OUT> submit(Task<IN, OUT> task, IN input);
// 提交需要返回值的任務 回調函數
Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback);
// 使用靜態方法構建一個FutureService
static <T, R> FutureService<T, R> newService() {
return new FutureServiceImpl<>();
}
}
Task接口設計
package com.jiang.currents.future;
/**
* @ClassName Task.java
* @Description Task接口主要是體提供給調用者實現計算邏輯使用的
* @createTime 2019年10月31日
*/
public interface Task<IN, OUT> {
// 給定一個參數,經過計算返回結果
OUT get(IN input);
}
Callback回調接口
package com.jiang.currents.future;
/**
* @ClassName Callback.java
* @Description TODO
* @createTime 2019年10月31日
*/
public interface Callback<T> {
//任務完成後會調用該方法, 其中T爲任務執行後的結果
void call(T t);
}
程序實現
FutureTask是Future的一個實現,除了實現Future中定義的get()以及done()方法。還額外增加了protected方法finish方法
package com.jiang.currents.future;
/**
* @ClassName FutureTask.java
* @Description TODO
* @createTime 2019年10月31日
*/
public class FutureTask<T> implements Future<T> {
// 計算結果
private T result;
// 是否已經完成
private boolean isDone = false;
// 定義對象鎖
private final Object LOCK = new Object();
@Override
public T get() throws InterruptedException {
synchronized (LOCK) {
// 當任務還沒有完成時,調用get方法被掛起,進入阻塞
while (!isDone) {
LOCK.wait();
}
}
// 計算返回結果
return result;
}
//設置計算結果
protected void finish(T result) {
synchronized (LOCK) {
if (isDone) {
return;
}
#計算完成,並將isDone 設置爲true,同時喚醒阻塞中的線程
this.result = result;
this.isDone = true;
LOCK.notifyAll();
}
}
@Override
public boolean done() {
return isDone;
}
}
FutureServiceImpl
package com.jiang.currents.future;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 當提交任務的時候,創建一個信息的線程來受理該任務,進而達到任務異步執行的效果
*
* @param <IN>
* @param <OUT>
*/
public class FutureServiceImpl<IN, OUT> implements FutureService<IN, OUT> {
// 爲執行的線程指定名字前綴
private final static String FUTURE_THREAD_PREFIX = "FUTURE-";
private final AtomicInteger nextCounter = new AtomicInteger(0);
private String getNextName() {
return FUTURE_THREAD_PREFIX + nextCounter.getAndIncrement();
}
@Override
public Future<?> submit(Runnable runnable) {
final FutureTask<Void> future = new FutureTask<>();
new Thread(() -> {
runnable.run();
future.finish(null);
}, getNextName()).start();
return future;
}
@Override
public Future<OUT> submit(Task<IN, OUT> task, IN input) {
final FutureTask<OUT> future = new FutureTask<>();
new Thread(() -> {
OUT result = task.get(input);
// 設置返回結果
future.finish(result);
}, getNextName()).start();
return future;
}
@Override
public Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback) {
final FutureTask<OUT> future = new FutureTask<>();
new Thread(() -> {
OUT result = task.get(input);
// 設置返回結果
future.finish(result);
if (null != callback) {
// 回調函數
callback.call(result);
}
}, getNextName()).start();
return future;
}
}
Future主要是耗費時間的操作交給另外一個線程執行,從而達到異步的目的,而不是阻塞等待結果的返回。
import java.util.concurrent.TimeUnit;
/**
* @ClassName FutureTest01.java
* @Description 提交無返回值的任務
* @createTime 2019年10月31日
*/
public class FutureTest01 {
public static void main(String[] args) throws InterruptedException {
FutureService<Void, Void> service = FutureService.newService();
Future<?> future = service.submit(() -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am finish done .");
});
//get 方法 會使當前線程進入阻塞狀態
future.get();
}
}
package com.jiang.currents.future;
import java.util.concurrent.TimeUnit;
/**
* @ClassName FutureTest02.java
* @Description 提交有返回值的任務
* @createTime 2019年10月31日
*/
public class FutureTest02 {
public static void main(String[] args) throws InterruptedException {
//定義一個有返回值的FutureService
FutureService<String, Integer> service = FutureService.newService();
//submitf方法立即返回
Future<Integer> future = service.submit(input -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return input.length();
}, "Hello");
//get 方法 會使當前線程進入
System.err.println(future.get());
}
}
package com.jiang.currents.future;
import java.util.concurrent.TimeUnit;
/**
* @ClassName FutureTest03.java
* @Description 提交有返回值的任務 支持回調函數
* @createTime 2019年10月31日
*/
public class FutureTest03 {
public static void main(String[] args) throws InterruptedException {
FutureService<String, Integer> service = FutureService.newService();
Future<Integer> future = service.submit(input -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return input.length();
}, "Hello", System.out::println);
}
}
使用任務完成時hi回調機制可以讓調用者不在進行顯示get方式獲取數據而進入阻塞。