1. 如何写一个“异步函数”
我们平常编程写的函数 几乎都是同步调用函数,那么我们如何写一个异步执行的函数呢?!我想这个问题也许是哪些比较喜欢专研的程序员或者具有专研精神的人士回提出的问题吧!我们很多人已经习惯了windows系统提供的一些异步机制,使用这些异步机制我们很快的就能实现一些异步操作甚至可以很容易的实现一个异步执行的函数;但是我们研究过实现一个“异步函数”的本质吗?!
在单线程的系统中,所以的指令执行都是顺序执行的,这就暗示了如果一个函数A中调用了函数B,则A必须等到B执行后才能继续执行A中剩下的代码。
在多线程中,如果我们有一个threadA线程,在该线程中调用了一个函数C,而该C函数我们想将它实现成异步执行的,而异步执行必须要有多线程支持;如果我们在Windows中编写程序,创建一个线程是很简单只要使用
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId);
函数就可以创建一个线程。
那么我们按如下方式可以实现一个异步的FuncC函数:
(1)先把你要异步完成的工作单独写成要给函数,如
DWORD WINAPI AsyncronousThread(
LPVOID lpParameter // thread data){
..}(2)在函数FuncC中使用CreateThtread函数将(1)中的函数创建一成一个线程,然后直接返回。
CreateThread(。.,AsyncronousThread,。);return;}当然,写一个异步函数的方法很多,但是一个本质不会变,就是必须要依据多线程才能实现。
2. 什么是异步编程
传统的同步编程是一种请求响应模型,调用一个方法,等待其响应返回.
异步编程就是要重新考虑是否需要响应的问题,也就是缩小需要响应的地方。因为越快获得响应,就是越同步化,顺序化,事务化,性能差化。
异步编程通常是通过fire and forget方式实现,发射事件后即忘记,做别的事情了,无需立即等待刚才发射的响应结果了。(发射事件的地方称为生产者,而将在另外一个地方响应事件的处理者称为消费者).异步编程是一种事件驱动编程,需要完全改变思路,将“请求响应”的思路转变到“事件驱动”思路上,是一种软件编程思维的转变.下面几种你看参考一下
1、异步编程模型 (APM) 模式(也称为 IAsyncResult 模式),其中异步操作要求 Begin 和 End 方法(例如,异步写操作的 BeginWrite 和 EndWrite)。对于新的开发工作不再建议采用此模式。
2、基于事件的异步模式 (EAP) 需要一个具有 Async 后缀的方法,还需要一个或多个事件、事件处理程序、委托类型和 EventArg 派生的类型。EAP 是在 .NET Framework 2.0 版中引入的。对于新的开发工作不再建议采用此模式。
3、基于任务的异步模式 (TAP),该模式使用一个方法表示异步操作的启动和完成。.NET Framework 4 中引入了 TAP,并且是 .NET Framework 中异步编程的建议方法。
3. java 异步编程
用异步输入输出流编写Socket进程通信程序 在Merlin中加入了用于实现异步输入输出机制的应用程序接口包:java.nio(新的输入输出包,定义了很多基本类型缓冲(Buffer)),java.nio.channels(通道及选择器等,用于异步输入输出),java.nio.charset(字符的编码解码)。
通道(Channel)首先在选择器(Selector)中注册自己感兴趣的事件,当相应的事件发生时,选择器便通过选择键(SelectionKey)通知已注册的通道。然后通道将需要处理的信息,通过缓冲(Buffer)打包,编码/解码,完成输入输出控制。
通道介绍: 这里主要介绍ServerSocketChannel和 SocketChannel.它们都是可选择的(selectable)通道,分别可以工作在同步和异步两种方式下(注意,这里的可选择不是指可以选择两种工作方式,而是指可以有选择的注册自己感兴趣的事件)。可以用channel.configureBlocking(Boolean )来设置其工作方式。
与以前版本的API相比较,ServerSocketChannel就相当于ServerSocket(ServerSocketChannel封装了ServerSocket),而SocketChannel就相当于Socket(SocketChannel封装了Socket)。当通道工作在同步方式时,编程方法与以前的基本相似,这里主要介绍异步工作方式。
所谓异步输入输出机制,是指在进行输入输出处理时,不必等到输入输出处理完毕才返回。所以异步的同义语是非阻塞(None Blocking)。
在服务器端,ServerSocketChannel通过静态函数open()返回一个实例serverChl。然后该通道调用serverChl.socket().bind()绑定到服务器某端口,并调用register(Selector sel, SelectionKey.OP_ACCEPT)注册OP_ACCEPT事件到一个选择器中(ServerSocketChannel只可以注册OP_ACCEPT事件)。
当有客户请求连接时,选择器就会通知该通道有客户连接请求,就可以进行相应的输入输出控制了;在客户端,clientChl实例注册自己感兴趣的事件后(可以是OP_CONNECT,OP_READ,OP_WRITE的组合),调用clientChl.connect(InetSocketAddress )连接服务器然后进行相应处理。注意,这里的连接是异步的,即会立即返回而继续执行后面的代码。
选择器和选择键介绍: 选择器(Selector)的作用是:将通道感兴趣的事件放入队列中,而不是马上提交给应用程序,等已注册的通道自己来请求处理这些事件。换句话说,就是选择器将会随时报告已经准备好了的通道,而且是按照先进先出的顺序。
那么,选择器是通过什么来报告的呢?选择键(SelectionKey)。选择键的作用就是表明哪个通道已经做好了准备,准备干什么。
你也许马上会想到,那一定是已注册的通道感兴趣的事件。不错,例如对于服务器端serverChl来说,可以调用key.isAcceptable()来通知serverChl有客户端连接请求。
相应的函数还有:SelectionKey.isReadable(),SelectionKey.isWritable()。一般的,在一个循环中轮询感兴趣的事件(具体可参照下面的代码)。
如果选择器中尚无通道已注册事件发生,调用Selector.select()将阻塞,直到有事件发生为止。另外,可以调用selectNow()或者select(long timeout)。
前者立即返回,没有事件时返回0值;后者等待timeout时间后返回。一个选择器最多可以同时被63个通道一起注册使用。
应用实例: 下面是用异步输入输出机制实现的客户/服务器实例程序――程序清单1(限于篇幅,只给出了服务器端实现,读者可以参照着实现客户端代码): 程序类图public class NBlockingServer {int port = 8000;int BUFFERSIZE = 1024;Selector selector = null;ServerSocketChannel serverChannel = null;HashMap clientChannelMap = null;//用来存放每一个客户连接对应的套接字和通道public NBlockingServer( int port ) {this.clientChannelMap = new HashMap();this.port = port;}public void initialize() throws IOException {//初始化,分别实例化一个选择器,一个服务器端可选择通道this.selector = Selector.open();this.serverChannel = ServerSocketChannel.open();this.serverChannel.configureBlocking(false);InetAddress localhost = InetAddress.getLocalHost();InetSocketAddress isa = new InetSocketAddress(localhost, this.port );this.serverChannel.socket().bind(isa);//将该套接字绑定到服务器某一可用端口}//结束时释放资源public void finalize() throws IOException {this.serverChannel.close();this.selector.close();}//将读入字节缓冲的信息解码public String decode( ByteBuffer byteBuffer ) throws CharacterCodingException {Charset charset = Charset.forName( "ISO-8859-1" );CharsetDecoder decoder = charset.newDecoder();CharBuffer charBuffer = decoder.decode( byteBuffer );String result = charBuffer.toString();return result;}//监听端口,当通道准备好时进行相应操作public void portListening() throws IOException, InterruptedException {//服务器端通道注册OP_ACCEPT事件SelectionKey acceptKey =this.serverChannel.register( this.selector,SelectionKey.OP_ACCEPT );//当有已注册的事件发生时,select()返回值将大于0while (acceptKey.selector().select() > 0 ) {System.out.println("。
4. 深刻理解异步和同步以及异步编程有哪些方式
同步的概念:执行一个方法或者功能,在没得到结果前,其他方法不执行,一定得等当前方法执行完,才会执行下一步骤 异步的概念:执行一个方法或者功能,不需要等待到当前方法执行完,其他方法也可以执行 一. Javascript异步编程 Javascript是单线程的,因此异步编程对其尤为重要。
nodejs来说,外壳是一层js语言,这是用户操作的层面,在这个层次上它是单线程运行的,也就是说我们不能像Java、Python这类语言在语言级别使用多线程能力。取而代之的是,nodejs编程中大量使用了异步编程技术,这是为了高效使用硬件,同时也可以不造成同步阻塞。
不过nodejs在底层实现其实还是用了多线程技术,只是这一层用户对用户来说是透明的,nodejs帮我们做了几乎全部的管理工作,我们不用担心锁或者其他多线程编程会遇到的问题,只管写我们的异步代码就好。二. Javascript异步编程的方法 在ES6之前,js主要的异步编程方式有3种:(1) 回调函数 异步调用一般分为两个阶段,提交请求和处理结果,这两个阶段之间有事件循环的调用,它们属于两个不同的事件循环(tick),彼此没有关联。
异步调用一般以传入callback的方式来指定异步操作完成后要执行的动作。而异步调用本体和callback属于不同的事件循环。
一旦我们在异步调用函数中扔出一个异步I/O请求,异步调用函数立即返回,此时,这个异步调用函数和这个异步I/O请求没有任何关系。//定义主函数,回调函数作为参数 function A(a,callback) { callback(); console.log('我是主函数'); }//定义回调函数 function B(){ setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作 }//调用主函数,将函数B传进去 A(2,B);//输出结果 我是主函数 我是回调函数 一下是nodejs 读取文件的列子://读文件后输出文件内容 var fs = require('fs'); fs.readFile('./text1.txt', 'utf8', function(err, data){ if (err){ throw err; } console.log(data); });假如读取多个文件嵌套式,回调少还好管理,多了就比较繁琐不容易维护,比较混乱,回调太多,这就是“回调地狱(callback hell)” var fs = require('fs'); fs.readFile('./text1.txt', 'utf8', function(err, data){ fs.readFile('./text1.txt', 'utf8', function(err, data){ fs.readFile('./text1.txt', 'utf8', function(err, data){ });});});由此,Promise的概念就由社区提出并实现,作用与回调方法几乎一致,都是在某种情况下执行预先设定好的方法,但是使用它却能够让代码变得更简洁清晰(2)事件监听(事件的订阅和发布)//jq 的注册侦听事件$(".ele").on("click",function(){ console.log("clicking");});//触发事件$(".ele").trigger("click");//nodejs发布和订阅事件 var events = require('events'); var emitter = new events.EventEmitter(); emitter.on('event1', function(message){ console.log(message); }); emitter.emit('event1', "message for you"); (3)ES6 Promise 在ES6发布了,Promise是异步编程的解决方案的一种 什么是Promise Promise是异步编程的一种解决方案,它有三种状态,分别是pending-进行中、resolved-已完成、rejected-已失败 当Promise的状态又pending转变为resolved或rejected时,会执行相应的方法,并且状态一旦改变,就无法再次改变状态,这也是它名字promise-承诺的由来 promise对象://实例化的Promise对象会立即执行 let promise = new Promise ( (resolve, reject) => { if ( success ) { resolve(a) // pending ——> resolved 参数将传递给对应的回调方法 } else { reject(err) // pending ——> rejectd } } ) Promise原型链上的then 方法.then()方法是Promise原型链上的方法,它包含两个参数方法,分别是已成功resolved的回调和已失败rejected的回调 Promise原型链上的catch 方法 Promise catch()的作用是捕获Promise的错误,与then()的rejected回调作用几乎一致。
但是由于Promise的抛错具有冒泡性质,能够不断传递,这样就能够在下一个catch()中统一处理这些错误。同时catch()也能够捕获then()中抛出的错误,所以建议不要使用then()的rejected回调,而是统一使用catch()来处理错误 Promise的基本Api方法:Promise.resolve() 用来包装一个现有对象,将其转变为Promise对象,但Promise.resolve()会根据参数情况返回不同的Promise:参数是Promise:原样返回 参数带有then方法:转换为Promise后立即执行then方法 参数不带then方法、不是对象或没有参数:返回resolved状态的Promise Promise.reject() Promise.reject()会直接返回rejected状态的Promise Promise.all()//参数为Promise对象数组 Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
p的状态由p1、p2、p3决定,分两种情况:(1)只有p1、p2、p3的状态都变成resolved,p的状态才会变成resolved,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
Promise.race()//参数为Promise对象数组 参数中的p1、p2、p3只要有一个改变状态,promise就会立刻变成相。
5. JAVA控制两个线程异步进行要怎么写啊
这个是最简单易懂的例子,自己手写的,还有一种是实现接口的,和这个差不多,需要的话可以给你写,希望对你有帮助
public class Test extends Thread{
private String name;
public Test() {
};
public Test (String name){
this.name=name;
}
public void run(){
for (int i = 0; i
6. C#几种异步编程
1、异步编程模型 (APM) 模式(也称为 IAsyncResult 模式),其中异步操作要求 Begin 和 End 方法(例如,异步写操作的 BeginWrite 和 EndWrite)。对于新的开发工作不再建议采用此模式。
2、基于事件的异步模式 (EAP) 需要一个具有 Async 后缀的方法,还需要一个或多个事件、事件处理程序、委托类型和 EventArg 派生的类型。EAP 是在 .NET Framework 2.0 版中引入的。对于新的开发工作不再建议采用此模式。
3、基于任务的异步模式 (TAP),该模式使用一个方法表示异步操作的启动和完成。.NET Framework 4 中引入了 TAP,并且是 .NET Framework 中异步编程的建议方法。