PHP异步执行的常用方式常见的有以下几种,可以根据各自优缺点进行选择:

1.客户端页面采用AJAX技术请求服务器
优点
:最简单,也最快,就是在返回给客户端的HTML代码中,嵌入AJAX调用,或者,嵌入一个img标签,src指向要执行的耗时脚本。
缺点:一般来说Ajax都应该在onLoad以后触发,也就是说,用户点开页面后,就关闭,那就不会触发我们的后台脚本了。
而使用img标签的话,这种方式不能称为严格意义上的异步执行。用户浏览器会长时间等待php脚本的执行完成,也就是用户浏览器的状态栏一直显示还在load。
当然,还可以使用其他的类似原理的方法,比如script标签等等。

2.popen()函数
该函数打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。
所以可以通过调用它,但忽略它的输出。使用代码如下:

pclose(popen("/home/xinchen/backend.php &", 'r'));

优点:避免了第一个方法的缺点,并且也很快。
缺点:这种方法不能通过HTTP协议请求另外的一个WebService,只能执行本地的脚本文件。并且只能单向打开,无法穿大量参数给被调用脚本。并且如果,访问量很高的时候,会产生大量的进程。如果使用到了外部资源,还要自己考虑竞争。

3.CURL扩展
CURL是一个强大的HTTP命令行工具,可以模拟POST/GET等HTTP请求,然后得到和提取数据,显示在"标准输出"(stdout)上面。代码如下:

$ch = curl_init();$curl_opt = array(CURLOPT_URL, 'http://www.example.com/backend.php',CURLOPT_RETURNTRANSFER, 1,CURLOPT_TIMEOUT, 1,);
curl_setopt_array($ch, $curl_opt);
curl_exec($ch);
curl_close($ch);

缺点如你问题中描述的一样,由于使用CURL需要设置CUROPT_TIMEOUT为1(最小为1,郁闷)。也就是说,客户端至少必须等待1秒钟。(等不等带1秒没有验证,我感觉不用吧)

4.fscokopen()函数
fsockopen支持socket编程,可以使用fsockopen实现邮件发送等socket程序等等,使用fcockopen需要自己手动拼接出header部分
可以参考: http://cn.php.net/fsockopen/
使用示例如下:

$fp = fsockopen("www.34ways.com", 80, $errno, $errstr, 30);
if (!$fp) {echo "$errstr ($errno)<br />\n";
} else {$out = "GET /index.php  / HTTP/1.1\r\n";$out .= "Host: www.34ways.com\r\n";$out .= "Connection: Close\r\n\r\n";fwrite($fp, $out);/*忽略执行结果while (!feof($fp)) {echo fgets($fp, 128);}*/fclose($fp);
}

所以总结来说,fscokopen()函数应该可以满足您的要求。可以尝试一下。

fscokopen的问题和popen 一样,并发非常多时会产生很多子进程,当达到apache的连接限制数时,就会挂掉,我问题已经说了这种情况。

  

PHP 本身没有多线程的东西,但可以曲线的办法来造就出同样的效果,比如多进程的方式来达到异步调用,只限于命令模式。还有一种更简单的方式,可用于 Web 程序中,那就是用fsockopen()、fputs() 来请求一个 URL 而无需等待返回,如果你在那个被请求的页面中做些事情就相当于异步了。

关键代码如下:

$fp=fsockopen('localhost',80,&$errno,&$errstr,5);
if(!$fp){echo "$errstr ($errno)<br />\n";
}
fputs($fp,"GET another_page.php?flag=1\r\n");
fclose($fp);

上面的代码向页面 another_page.php 发送完请求就不管了,用不着等待请求页面的响应数据,利用这一点就可以在被请求的页面 another_page.php 中异步的做些事情了。

比如,一个很切实的应用,某个 Blog 在每 Post 了一篇新日志后需要给所有它的订阅者发个邮件通知。如果按照通常的方式就是:

日志写完 -> 点提交按钮 -> 日志插入到数据库 -> 发送邮件通知 ->
告知撰写者发布成功

  

那么作者在点提交按钮到看到成功提示之间可能会等待很常时间,基本是在等邮件发送的过程,比如连接邮件服务异常、或器缓慢或是订阅者太多。而实际上是不管邮件发送成功与否,保证日志保存成功基本可接受的,所以等待邮件发送的过程是很不经济的,这个过程可异步来执行,并且邮件发送的结果不太关心或以日志形式记录备查。

改进后的流程就是:

日志写完 -> 点提交按钮 -> 日志插入到数据库 --->
告知撰写者发布成功
└ 发送邮件通知 -> [记下日志]

  

用个实际的程序来测试一下,有两个 php,分别是 write.php 和 sendmail.php,在 sendmail.php 用 sleep(seconds) 来模拟程序执行使用时间。

write.php,执行耗时 1 秒

<?php function asyn_sendmail() {$fp=fsockopen('localhost',80,&$errno,&$errstr,5);if(!$fp){echo "$errstr ($errno)<br />\n";}sleep(1);fputs($fp,"GET /sendmail.php?param=1\r\n"); #请求的资源 URL 一定要写对fclose($fp);
} echo time().'<br>';
echo 'call asyn_sendmail<br>';
asyn_sendmail();
echo time().'<br>';
?>
sendmail.php,执行耗时 10 秒<?php
//sendmail();
//sleep 10 seconds
sleep(10);
fopen('C:\'.time(),'w');
?>

通过页面访问 write.php,页面输出:

1272472697 call asyn_sendmail
1272472698

并且在 C:\ 生成文件:

1272472708

从上面的结果可知 sendmail.php 花费至少 10 秒,但不会阻塞到 write.php 的继续往下执行,表明这一过程是异步的。

php 不等待返回的实现方法(异步调用)相关推荐

  1. Spring 接口方法异步调用

    对外开放的接口,在被外部调用时,需要校验接收到的数据,校验通过后才能开始进行数据处理,处理完成后向特定地址返回结果. 校验通过后即返回接口调用的响应信息,就涉及到方法的异步调用.在 Spring 框架 ...

  2. WinForm 异步调用方法

    假如要在一个线程中异步执行一个方法,则先创建一个该方法的委托类型,然后CLR会自动为该委托类型定义一个BeginInvoke方法和EndInvoke方法,我们就靠这两个方法异步调用委托类型指向的方法( ...

  3. Java中带返回值的方法的定义与调用

    带返回值的方法定义: public static 数据类型 方法名(参数){return 数据;} 与前文中带返回值的方法定义不同的是,void变成了数据类型,对应return后紧跟的数据.这里顺便说 ...

  4. Dubbo 同步、异步调用的几种方式

    我们知道,Dubbo 缺省协议采用单一长连接,底层实现是 Netty 的 NIO 异步通讯机制:基于这种机制,Dubbo 实现了以下几种调用方式: 同步调用 异步调用 参数回调 事件通知 同步调用 同 ...

  5. Direct3D Draw函数 异步调用原理解析

    概述 在D3D10中,一个基本的渲染流程可分为以下步骤: 清理帧缓存: 执行若干次的绘制: 通过Device API创建所需Buffer: 通过Map/Unmap填充数据到Buffer中: 将Buff ...

  6. C#中的异步调用剖析

    我上次写创建线程的时候就想写一篇深入异步调用的笔记,但是由于当时对windows的进程与线程的概念不太清楚,没敢写,今天我仔细的分析并调试了一下C#中的异步调用的四种方法.把学习笔记分享出来. 假如要 ...

  7. delphi 异步 调用 带参数_Dubbo 关于同步/异步调用的几种方式

    我们知道,Dubbo 缺省协议采用单一长连接,底层实现是 Netty 的 NIO 异步通讯机制:基于这种机制,Dubbo 实现了以下几种调用方式: 同步调用 异步调用 参数回调 事件通知 同步调用 同 ...

  8. WebService大讲堂之Axis2(8):异步调用WebService

     在前面几篇文章中都是使用同步方式来调用WebService.也就是说,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止.使用同步方法来调用WebService ...

  9. jdbctemplate mysql 分页查询 返回list对象_spring jdbctemplate调用存储过程,返回list对象...

    spring jdbctemplate调用存储过程,返回list对象 方法: /** * 调用存储过程 * @param spName */ @SuppressWarnings("unche ...

最新文章

  1. python 红黑树_python学习笔记|红黑树(性质与插入)
  2. abstract interface 和 interface 没有区别
  3. tomcat java环境变量配置
  4. [PLM专题] 十分钟了解文本分类通用训练技巧
  5. Mybatis生成器插件扩展,定制方法生成,list参数生成
  6. 鸿蒙历程和路标图,华为鸿蒙OS:为生态而生,亦为生态所累
  7. keep-alive + vuex + mint + Infinite scroll 保存分页列表数据
  8. 学python能赚钱吗-在校大学生用python当爬虫一个月能赚3000吗?
  9. ios控件 UIViewController
  10. 一个员工经常找别人聊天,吾就知道他要走人了
  11. ListView的item监听事件,并且把值传递给另一个activity
  12. Ubuntu下用snap7与西门子通信
  13. matlab简单函数画图例题,Matlab(十) 简单的函数画图
  14. 如何修改服务器ntp配置,[修改]Linux下NTP服务器的配置
  15. Flutter学习笔记
  16. Leetcode 739. Daily Temperatures
  17. HSL、RGB颜色转换
  18. AngularJS中的双向数据绑定
  19. Vue控制表格列的显示隐藏
  20. JSTL【一】C标签的使用

热门文章

  1. wpf slider 控件模板
  2. 字符串一:替换空格()
  3. 京东方拟收购法国零售物联网领域公司50.1%以上股份
  4. WebSocket 实战
  5. h5直播开发之旅总结
  6. python -- 青少年如何使用 Python 开始游戏开发
  7. 华为×××+IPSEC实现安全连接
  8. 在MAC上搭建eclipse+android开发环境
  9. 使用Keil MDK以及标准外设库创建STM32工程
  10. 8.11 更改用户ID和组ID