回调面向接口的实现:
回调的简单实现:
package netty.in.action;
/**
* Created with IntelliJ IDEA.
* Description: 声明回调接口
* User: zhubo
* Date: 2018-01-31
* Time: 10:04
*/
public interface FetcherCallback {
void onData(Data data) throws Exception;
void onError(Throwable cause);
}
package netty.in.action;
/**
* Created with IntelliJ IDEA.
* Description: 声明业务接口
* User: zhubo
* Date: 2018-01-31
* Time: 10:03
*/
public interface Fetcher {
void fetchData(FetcherCallback callback);
}
package netty.in.action;
/**
* Created with IntelliJ IDEA.
* Description: 业务接口实现类
* User: zhubo
* Date: 2018-01-31
* Time: 10:06
*/
public class MyFetcher implements Fetcher {
final Data data;
public MyFetcher(Data data) {
this.data = data;
}
/**
* 实现业务逻辑 执行完后回调数据
* @param callback
*/
@Override
public void fetchData(FetcherCallback callback) {
try{
//执行业务代码
// 调用回调
callback.onData(data);
}catch (Exception e){
callback.onError(e);
}
}
}
package netty.in.action;
/**
* Created with IntelliJ IDEA.
* Description:
* User: zhubo
* Date: 2018-01-31
* Time: 10:03
*/
public class Worker {
public void doWork() {
Fetcher fetcher = new MyFetcher(new Data(2,3));
fetcher.fetchData(new FetcherCallback() {
@Override
public void onData(Data data) throws Exception {
System.out.println("Data received: " + data);
}
@Override
public void onError(Throwable cause) {
System.out.println("An error accour: " + cause.getMessage());
}
});
}
public static void main(String[] args) {
Worker w = new Worker();
w.doWork();
}
}
package netty.in.action;
/**
* Created with IntelliJ IDEA.
* Description:
* User: zhubo
* Date: 2018-01-31
* Time: 10:04
*/
public class Data {
private int n;
private int m;
public Data(int n, int m) {
this.n = n;
this.m = m;
}
@Override
public String toString() {
return "Data{" +
"n=" + n +
", m=" + m +
'}';
}
}
上面的例子是一个简单的模拟回调,要明白其所表达的含义。Fetcher.fetchData()方法需传递一个FetchCallback类型的参数,当获得数据或发生错误时被调用。对于每种情况都提供了统一的方法。
- FetcherCallback.onData() , 将接受数据时被调用。
- FetcherCallback.onError() , 发生错误时被调用。
因为可以将这些方法的执行从“caller”线程移动到其他的线程执行; 但也不会保证FetcherCallback的每个方法都会被执行。回调过程有个问题就是当你使用链式调用,很多不同的方法会导致线性代码;
Futures:
第二种技术是使用Futures,Futures是一个抽象概念,它标识一个值,该值可能在某一点变得可用。一个Future 要么获得计算完的结果,要么获得计算失败后的异常,Java在java.util.current包中附带了Future接口。例如下面的代码,每传递一个Runnable对象到ExecutorService.submit() 方法就会得到一个回调的Future。你能使用它检测是否执行完成。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created with IntelliJ IDEA.
* Description: Future实现异步回调
* User: zhubo
* Date: 2018-01-31
* Time: 14:11
*/
public class FutureExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
Runnable task1 = new Runnable() {
@Override
public void run() {
System.out.println("i am task1.....");
}
};
Callable<Integer> task2 = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return new Integer(100);
}
};
Future<?> f1 = executor.submit(task1);
Future<Integer> f2 = executor.submit(task2);
System.out.println("task1 is completed? " + f1.isDone());
System.out.println("task2 is completed? " + f2.isDone());
while(f2.isDone()){
System.out.println("return value by task2: " + f2.get());
break;
}
while(f1.isDone()){
System.out.println("task1 completed." + f1.get());
break;
}
}
}