zoukankan      html  css  js  c++  java
  • 我所使用的异步编程

    JavaScript在异步处理上十分方便,最一开始用到异步是JavaScript封装框架jQuery来请求后台的代码
    $.post(url,param,callback)
    而这种方式需要提供回调函数
    但是回调函数可能会出现这样的窘境:
    一个回调的经典场景:nodejs中mongoDB的查询使用
    var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});
    p_client.open(function(err, p_client) {
        p_client.dropDatabase(function(err, done) {
            p_client.createCollection('test_custom_key', function(err, collection) {
                collection.insert({'a':1}, function(err, docs) {
                    collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) {
                        cursor.toArray(function(err, items) {
                            test.assertEquals(1, items.length);
    
                            // Let's close the db
                            p_client.close();
                        });
                    });
                });
            });
        });
    });

    为了解决多层异步不利于理解和调错的问题,ES6引入了新的对象,Promise
    mozilla官方对它的定义是:
    Promise 对象用于异步(asynchronous)计算.。一个Promise对象代表着一个还未完成,但预期将来会完成的操作
    在我看来Promise是一个包含自执行器的状态机
    我们模拟一下Promise的实现
    //全局宏定义
    var PENDING = 0;
    var FULFILLED = 1;
    var REJECTED = 2;
    //Promise构造函数
    function Promise(fn){
        var self = this;
        self.state = PENDING;//初始化状态
        self.value = null;//存储异步结果的对象变量
        self.handlers = [];//存储回调函数,这里没保存失败回调函数,因为这是一个dome
        //异步任务成功后处理,这不是回调函数
        function fulfill(result){
            if(self.state === PENDING){
                self.state = FULFILLED;
                self.value = result;
                for(var i=0;i<self.handlers.length;i++){
                    self.handlers[i](result);
                }
     
            }
        }
     
        //异步任务失败后的处理,
        function reject(err){
            if(self.state === PENDING){
                self.state = REJECTED;
                self.value = err;
            }
        }   
        fn&&fn(fulfill,reject);
     
    };
     
    //使用then方法添加回调函数,把这次回调函数return的结果当做return的promise的resolve的参数
    Promise.prototype.then = function(onResolved, onRejected){
        var self = this;
        return new Promise(function(resolve, reject){
            var onResolvedFade = function(val){
                var ret = onResolved?onResolved(val):val;//这一步主要是then方法中传入的成功回调函数通过return来进行链式传递结果参数
                if(Promise.isPromise(ret)){//回调函数返回值也是promise的时候
                    ret.then(function(val){
                        resolve(val);
                    });
                }
                else{
                    resolve(ret);
                }
            };
            var onRejectedFade = function(val){
                var ret = onRejected?onRejected(val):val;
                reject(ret);
            };
            self.handlers.push(onResolvedFade);
            if(self._status === FULFILLED){
                onResolvedFade(self._value);
            }
     
            if(self._status === REJECTED){
                onRejectedFade(self._value);
            }
        });
    }
    使用如下:
    function p(value){
        var pms = new Promise(function(resolve, reject){
            setTimeout(function(){
                resolve(value);;
            }, 1000);
        });
        return pms;
    }
    p(1).then(function(result){
        console.log('the result is ',result);//the result is 2 
        return result;
    }).then(function(result){
        console.log(++result);//2
    });
    成功进入resolve参数,失败则进入reject函数
    ES6中提供的Promise还有捕获异常的catch组件
    更进一步,ES6中实现了C#中存在的async   await 关键字,如下:
    其中async对修饰函数做了一个Promise封装
     
    function timeout(ms){
        return new Promise((resolve)=>{
            setTimeout(resolve,ms);
        })
    }
     
    async function asyncPrint(value,ms){
        await timeout(ms);
        console.log(value);
    }
     
    asyncPrint('hello world',1000);
     
    console.log('end');
    APM
    C#中对应的叫做APM( Asynchronous Programming Model)
    基于回调的异步实现,类似的实现BeginInvoke异步方法的类
     
    java中的异步回调稍微麻烦一些,可以自己实现
    public class CallBackTest extends AbstractCallBack {
          public CallBackTest(CallHandler handler) {
                super(handler);
          }
          public static void main(String[] args) {
                CallBackTest callTest = new CallBackTest(new CallHandler() {
                      @Override
                      public void handler(String param) {
                            System.out.println("处理参数:" + param);
                      }
                });
                callTest.start("参数1");
          }
          @Override
          void after() {
                System.out.println("回调处理");
          }
    }
    //异步处理
    abstract class AbstractCallBack {
          private CallHandler callHandler;
          public final void start(final String param) {
                new Thread(new Runnable() {
                      @Override
                      public void run() {
                            callHandler.handler(param);
                            after();
                      }
                }).start();       
          }
          public AbstractCallBack(CallHandler handler) {
                this.callHandler = handler;
          }
          abstract void after();
    }
    //回调函数接口
    interface CallHandler {
          public void handler(String param);
    }
     
    TAP 基于任务的异步模式,Task-based Asynchronous Pattern
    Java并发包中已经有相应的实现了,我们可以用 FutureTask达到相应的效果:
    public class futureTaskTest {
          public static void main(String[] args) {
                ExecutorService executor = Executors.newCachedThreadPool();
                for (int i = 0; i < 5; i++) {
                      Callable<String> c = new Task();
                      MyFuture ft = new MyFuture(c);
                      executor.submit(ft);
                }
                executor.shutdown();
          }
    }
    class MyFuture extends FutureTask<String> {
          public MyFuture(Callable<String> callable) {
                super(callable);
          }
          public void done() {
                System.out.println(" 线程执行完毕!~");
          }
    }
    class Task implements Callable<String> {
          @Override
          public String call() throws Exception {
                // TODO Auto-generated method stub
                Thread.sleep(1000);
                System.out.println(" 执行中");
                return Thread.currentThread().getName();
          }
    }
    Event-based Asynchronous Pattern基于事件的异步
    参考我先前的一篇文章,基于观察者模式实现java的事件:http://www.cnblogs.com/wanglao/p/5305076.html
    将其异步化,改变事件监听者(事件处理),然后在事件源的触发器中增加线程控制:
    abstract class Handler implements EventListener, Runnable {
          EventState state;
          public Handler(EventState state) {
                this.state = state;
          }
          public void doHandler() {
                System.out.println("handler1 执行了,现在状态是:" + state);
          }
          public void run() {
                doHandler();
          }
    }
    //事件执行
                 protected void notifies(EventState sate){
                       if ( eventListeners.size()>0) {
                             for (Handler handler : eventListeners) {
                                  new Thread(handler).start();
                            }
                      }
                }
    另外,一些设计模式也是天生适合异步多线程环境,比如生产者-消费模式。
     
     参考:http://www.cnblogs.com/zhaopei/p/async_one.html
     
  • 相关阅读:
    Python 正则表达式匹配两个指定字符串中间的内容
    Switch Case 和 If Else
    MYSQL LETT/RIGHT/INNER/FUll JOIN 注意事项
    MYSQL 批处理 Packet for query is too large
    Junit单元测试不支持多线程
    postman中 form-data、x-www-form-urlencoded、raw、binary的区别
    一个项目中:只能存在一个 WebMvcConfigurationSupport (添加swagger坑)
    Nginx 转发特点URL到指定服务
    基于UDP协议的程序设计
    TcpClient类与TcpListener类
  • 原文地址:https://www.cnblogs.com/wanglao/p/6564799.html
Copyright © 2011-2022 走看看