understand asynchrony

This article is reproduced from: http://blog.csdn.net/historyasamirror/article/details/6159248

 

The so-called synchronization, simply put, A tells B to do something, and then waits until B returns to A after finishing, and A continues to do other things; the
so-called asynchronous, on the contrary, A tells B to do something things, and then go to do other things, and then notify A when B is done.

Whether it is synchronous or asynchronous, it actually refers to the interaction between two objects. Therefore, to determine what is synchronous or asynchronous, first of all, it is necessary to clarify the relationship between the two objects.
for example:

 

[java]  view plain copy  
 
  1. socket.write(request);  
  2. response = socket.read();  

 

This is a common pseudocode for Client to send request to Server. Here, it can be said that socket.write is a synchronous IO, because after calling the write operation, the kernel will put the data to be written into the buffer of the network card, and then return, so the two objects synchronized here are the application program. And the kernel; it can also be said that this code is a synchronous message mechanism, because after the client sends the request to the server, it waits until the server returns the response. The two objects synchronized here are the client and the server.

The previous blog was devoted to synchronous IO and asynchronous IO, which refers to the relationship between the application and the operating system kernel. Not much to talk about here. Let's talk about Mina here. Mina is a very popular framework for network programs, it provides an asynchronous API (It provides an abstract • event-driven • asynchronous API).
For example, if the client wants to create a connection to the server, with mina you can write:

 

[java]  view plain copy  
 
  1.  NioSocketConnector connector = new NioSocketConnector();  
  2. // Initialize the connector...  
  3. //..........  
  4. connector.connect(address);  

 

It looks like it is no different from the normal writing. However, the connector.connect() method here is an asynchronous call, meaning that the program tells mina to connect to the address, and mina returns that it will do it, but it may not have done it yet. So, even if the "connector.connect(address);" line of code ends, it does not mean that the connection is successful (mina may still be in the process of creating a connection at this time). The complete writing should be:

 

[java]  view plain copy  
 
  1. ConnectFuture connFuture = connector.connect(address);  
  2. connFuture.addListener(new ConnectListener());  
  3.         privateclass ConnectListener implements IoFutureListener<ConnectFuture>{   
  4.               
  5.             publicvoid operationComplete(ConnectFuture future) {   
  6.                   
  7.                 if (future.isConnected()) {  
  8.                     //get session  
  9.                     IoSession session = future.getSession();  
  10.                       
  11.                     session.write(...);  
  12.                       
  13.                 } else {  
  14.                       
  15.                     logger.error("can not create the connection .");  
  16.                 }  
  17.             }  
  18.         }  
  19.     }  
  20. }  

 上面代码是原文我稍微做了下修改

    //future.awaitUninterruptibly();
        future.addListener(new IoFutureListener<ConnectFuture>()
        {
            @Override
            public void operationComplete(ConnectFuture future)
            {
                if(future.isConnected())
                {
                    System.out.println("connected");
                }else {
                    System.out.println("disconnected");
                }
            }
        });
        System.out.println("end");

 这里地址对网络通的情况下,future.awaitUninterruptibly()一行,注释掉则打印 end connected ,不注释掉则打印 connected end 可以稍微注意下

 

这里面最重要的一个类是ConnectListener,它实现了IoFutureListener<ConnectFuture>这个接口。这个类其实只有一个函数 – operationComplete,这是一个回调函数,它告诉mina一旦connect完成以后,就调用这个函数。我们这里的回调函数,首先判断一下连接是否成功,如果成功,那么就向这个链接中写入数据(session.write)。

回调函数在异步机制中扮演着非常重要的角色。 因为在同步机制中,调用者会等到结果返回然后自己执行接下来的操作,比如,上面这段代码如果写成同步的,大概是这个样子:

 

[java]  view plain  copy
 
  1. boolean status = connector.connect(address);  
  2. if(status) {  
  3.     session.write(...);  
  4. else {  
  5.     logger.error("can not create the connection .");  
  6. }  

 

但是在异步机制中,就只能将connect后面的代码做成回调函数,注册到mina中。这样,当mina完成工作后它才知道接下去该干什么。

值得一提的是,虽然Mina号称是Asynchronous API,但它也提供了同步的方法。比如,上面这段代码,如果用Mina的同步机制是这样写的:

 

[java]  view plain  copy
 
  1. ConnectFuture future = connector.connect(address);  
  2. future.awaitUninterruptibly();  
  3. IoSession session = future.getSession();  
  4.         // Send the first ping message  
  5.         session.write(....);  

 

重点在于“future.awaitUninterruptibly();”这行代码,它会将程序阻塞住,直到连接创建好,所以,当这行代码结束后,就可以直接获取session并执行write操作。

我在网上找到的大部分Mina示例代码都是基于同步的调用。所以,虽然很多人用mina,可是还是更习惯于同步的机制。至于为什么会这样,以后会再讨论。

 

 

上篇说了半天,却回避了一个重要的问题:为什么要用异步呢,它有什么样的好处?坦率的说,我对这点的认识不是太深刻(套句俗语,只可意会,不可言传)。还是举个例子吧:
比如Client向Server发送一个request,Server收到后需要100ms的处理时间,为了方便起见,我们忽略掉网络的延迟,并且,我们认为Server端的处理能力是无穷大的。在这个use case下,如果采用同步机制,即Client发送request -> 等待结果 -> 继续发送,那么,一个线程一秒钟之内只能够发送10个request,如果希望达到10000 request/s的发送压力,那么Client端就需要创建1000个线程,而这么多线程的context switch就成为client的负担了。而采用异步机制,就不存在这个问题了。Client将request发送出去后,立即发送下一个request,理论上,它能够达到网卡发送数据的极限。当然,同时需要有机制不断的接收来自Server端的response。

以上的例子其实就是这篇的主题,异步的消息机制,基本的流程是这样的:

If you think about it carefully, you will find that there are two very important problems in this process that need to be solved:
1. When the client receives the response, how to confirm it is the response of the previous request?
2. If a request is sent, the response corresponding to the request has not been returned due to various reasons (such as a problem on the server side). How can the client find a request that has not received a response for a long time?

For the first question, generally try to assign a unique ID to each request, and the returned Response will carry this ID at the same time, so that the request and the response can be matched.
For the second question, there needs to be a timeout mechanism. There is a timer for each request. If the result is still not returned by the specified time, the timeout operation will be triggered. To put it another way, the timeout mechanism is actually very necessary for the synchronization mechanism involving the network, because it is possible that the link between the client and the server is broken. In extreme cases, the client will be blocked all the time.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326276713&siteId=291194637