美文网首页
实现异步API的两个常用方法

实现异步API的两个常用方法

作者: 薛晨 | 来源:发表于2016-05-20 21:06 被阅读1231次

整个 Netty 的 API 都是异步的,异步处理不是一个新的机制,这个机制出来已经有一些时间了。对网络应用来说,IO 一般是性能的瓶颈,使用异步 IO 可以较大程度上􏰀高程序性能,因为异步变的越来越重要。但是它是如何工作的呢?以及有哪些不同的模式可用呢?

异步处理􏰀倡更有效的使用资源,它允许你创建一个任务,当有事件发生时将获得通知并等待事件完成。这样就不会阻塞,不管事件完成与否都会及时返回,资源利用率更高,程序可以利用剩余的资源做一些其他的事情。

本节将说明一起工作或实现异步 API 的两个最常用的方法,并讨论这些技术之间的差异

一、Callback(回调)

回调是异步处理的一种技术。一个回调是被传递到并且执行完该方法。
下面代码是一个简单的回调:

public class Worker {    

  public void doWork() {        
    Fetcher fetcher = new MyFetcher(new Data(1, 0));  
    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 err occured : " + cause.getMessage());            }        
        });    
   }    

   public static void main(String[] args) {        
        Worker w = new Worker();        
        w.doWork();    
   }
}
public interface Fetcher {    
    void fetchData(FetcherCallback callback);
}
public class MyFetcher implements Fetcher {    
    final Data data;    

    public MyFetcher(Data data) {        
        this.data = data;    
    }    

    @Override    
    public void fetchData(FetcherCallback callback) {        
        try {           
             callback.onData(data);        
        } catch (Exception e) {            
            callback.onError(e);        
        }    
    }
}
public interface FetcherCallback {    

    void onData(Data data) throws Exception;    
    void onError(Throwable cause);
}
public class Data {   
 
    private int m;    
    private int n;    

    public Data(int m, int n) {        
        this.m = m;        
        this.n = n;    
    }    

    @Override    
    public String toString() {        
        int r = n / m;        
        return n + "/" + m + " = " + r;    
    }
}

上面的例子只是一个简单的模拟回调,要明白其所表达的含义。Fetcher.fetchData()方法需传递一个FetcherCallback 类型的参数,当获得数据或发生错误时被回调。对于每种情况都􏰀供了同意的方法:

FetcherCallback.onData(),将接收数据时被调用

FetcherCallback.onError(),发生错误时被调用

因为可以将这些方法的执行从"caller"线程移动到其他的线程执行;但也不会保证 FetcherCallback 的每个方法都会被执行。回调过程有个问题就是当你使用链式调用很多不同的方法会导致线性代码;有些人认为这种链式调用方法会导致代码难以阅读,但是我认为这是一种风格和习惯问题。例如,基于 Javascript 的 Node.js 越来越受欢迎,它使用了大量的回调,许多人都认为它的这种方式利于阅读和编写。

二、Futures

第二种技术是使用 Futures。Futures 是一个抽象的概念,它表示一个值,该值可能在某一点变得可用。一个 Future 要么获得计算完的结果,要么获得计算失败后的异常。Java 在 java.util.concurrent 包中附带了 Future 接口,它使用 Executor 异步执行。例如下面的代码,每传递一个 Runnable 对象到 ExecutorService.submit()方法就会得到一个回调的 Future,你能使用它检测是否执行完成。

public class FutureExample {    
    public static void main(String[] args) {        
        ExecutorService executor = Executors.newCachedThreadPool();        
        Runnable task1 = new Runnable() {            

            @Override            
            public void run() {                
                // do something                
                System.out.println("i am task1...");            
            }        
        };        

        Callable<Integer> task2 = new Callable<Integer>() {            

            @Override            
            public Integer call() throws Exception {                
               // do something                
               return new Integer(100);            
            }        
        };        

        Future<?> f1 = executor.submit(task1);           
        Future<Integer> f2 = executor.submit(task2);    

        System.out.println("task1 is done ? " + f1.isDone());   
        System.out.println("task2 is done ? " + f2.isDone());        

        // waiting task1 done        
        while (f1.isDone()) {            
            System.out.println("task1 done");            
            break;        
        }        
        // waiting task2 done        
        while (f2.isDone()) {            
            System.out.println("task2 done");            
            break;        
        }    
    }
}

有时候使用 Future 感觉很丑陋,因为你需要间隔检查 Future 是否已完成,而使用回调会直接收到返回通知。看完这两个常用的异步执行技术后,你可能想知道使用哪个最好?这里没有明确的答案。事实上,Netty 两者都使用,􏰀供两全其美的方案。

相关文章

  • 实现异步API的两个常用方法

    整个 Netty 的 API 都是异步的,异步处理不是一个新的机制,这个机制出来已经有一些时间了。对网络应用来说,...

  • 关于异步函数的前世今生

    1、ES6、ES7、ES8中关于异步函数的处理办法 JS中常用的实现异步的方法 利用setTimout实现异步 动...

  • nodejs的fs模块学习

    fs 模块常用api方法 1.readFile,readFileSync 异步读取文件 readFile 第一个参...

  • LinkedList 方法详解

    通过阅读LinkedList的api, 自己用代码实现他的常用方法;

  • AlertDialog 实用API及其示例

    本文将介绍常用AlertDialog Api及其常用AlertDialog示例 常用API 常用方法 方法定义方法...

  • 04-Node 异步编程

    Node 异步编程同步方法和异步方法异步 API 的执行顺序异步编程回调地狱问题Promise 改造回调地狱代码a...

  • OC runtime 底层API解析

    关于class的API 交换方法API 替换方法的实现 交换方法的实现

  • Flutter 91: 图解 Dart 单线程实现异步处理之 F

    小菜前几天刚学习了 Future 实现异步操作的部分方法,主要包括构造方法和常用的静态方法;小菜今天继续学习 Fu...

  • 异步基础

    异步 为什么要用异步方法? 为什么异步很难 怎么异步? 基于回调这是传统的异步模型,最常用的方法,早期版本的C# ...

  • 异步

    api来自开源社区apizza.使用XMLHttpRequest实现异步访问.

网友评论

      本文标题:实现异步API的两个常用方法

      本文链接:https://www.haomeiwen.com/subject/ytbnrttx.html