PHP 异步执行方法,模拟多线程
PHP 本身没有多线程的东西,但可以曲线的办法来造就出同样的效果,比如多进程的方式来达到异步调用,只限于命令模式。还有一种更简单的方式,可用于 Web 程序中,那就是用 fsockopen()、fputs() 来请求一个 URL 而无需等待返回,如果你在那个被请求的页面中做些事情就相当于异步了。
关键代码如下:
上面的代码向页面 another_page.php 发送完请求就不管了,用不着等待请求页面的响应数据,利用这一点就可以在被请求的页面 another_page.php 中异步的做些事情了。
比如,一个很切实的应用,某个 Blog 在每 Post 了一篇新日志后需要给所有它的订阅者发个邮件通知。如果按照通常的方式就是:
日志写完 -> 点提交按钮 -> 日志插入到数据库 -> 发送邮件通知 -> 告知撰写者发布成功
那么作者在点提交按钮到看到成功提示之间可能会等待很常时间,基本是在等邮件发送的过程,比如连接邮件服务异常、或器缓慢或是订阅者太多。而实际上是不管邮件发送成功与否,保证日志保存成功基本可接受的,所以等待邮件发送的过程是很不经济的,这个过程可异步来执行,并且邮件发送的结果不太关心或以日志形式记录备查。
改进后的流程就是:
日志写完 -> 点提交按钮 -> 日志插入到数据库 ---> 告知撰写者发布成功
└ 发送邮件通知 -> [记下日志]
用个实际的程序来测试一下,有两个 php,分别是 write.php 和 sendmail.php,在 sendmail.php 用 sleep(seconds) 来模拟程序执行使用时间。
write.php,执行耗时 1 秒
sendmail.php,执行耗时 10 秒
通过页面访问 write.php,页面输出:
1272472697
call asyn_sendmail
1272472698
并且在 C:\ 生成文件:
1272472708
从上面的结果可知 sendmail.php 花费至少 10 秒,但不会阻塞到 write.php 的继续往下执行,表明这一过程是异步的。
参考:1. PHP多线程类
2. 浅析php中实现多线程
3. php实现多线程(实际是多进程,夸平台)
4. Using the POST method to read from a URL within a PHP script 永久链接 https://yanbin.blog/php-simulate-multithread/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
关键代码如下:
1$fp=fsockopen('localhost',80,&$errno,&$errstr,5);
2if(!$fp){
3 echo "$errstr ($errno)<br />\n";
4}
5fputs($fp,"GET another_page.php?flag=1\r\n");
6fclose($fp);上面的代码向页面 another_page.php 发送完请求就不管了,用不着等待请求页面的响应数据,利用这一点就可以在被请求的页面 another_page.php 中异步的做些事情了。
比如,一个很切实的应用,某个 Blog 在每 Post 了一篇新日志后需要给所有它的订阅者发个邮件通知。如果按照通常的方式就是:
日志写完 -> 点提交按钮 -> 日志插入到数据库 -> 发送邮件通知 -> 告知撰写者发布成功
那么作者在点提交按钮到看到成功提示之间可能会等待很常时间,基本是在等邮件发送的过程,比如连接邮件服务异常、或器缓慢或是订阅者太多。而实际上是不管邮件发送成功与否,保证日志保存成功基本可接受的,所以等待邮件发送的过程是很不经济的,这个过程可异步来执行,并且邮件发送的结果不太关心或以日志形式记录备查。
改进后的流程就是:
日志写完 -> 点提交按钮 -> 日志插入到数据库 ---> 告知撰写者发布成功
└ 发送邮件通知 -> [记下日志]
用个实际的程序来测试一下,有两个 php,分别是 write.php 和 sendmail.php,在 sendmail.php 用 sleep(seconds) 来模拟程序执行使用时间。
write.php,执行耗时 1 秒
1<?php
2
3function asyn_sendmail() {
4 $fp=fsockopen('localhost',80,&$errno,&$errstr,5);
5 if(!$fp){
6 echo "$errstr ($errno)<br />\n";
7 }
8 sleep(1);
9 fputs($fp,"GET /sendmail.php?param=1\r\n"); #请求的资源 URL 一定要写对
10 fclose($fp);
11}
12
13echo time().'<br>';
14echo 'call asyn_sendmail<br>';
15asyn_sendmail();
16echo time().'<br>';
17?>
sendmail.php,执行耗时 10 秒
1<?php
2//sendmail();
3//sleep 10 seconds
4sleep(10);
5fopen('C:\'.time(),'w');
6?>
通过页面访问 write.php,页面输出:
1272472697
call asyn_sendmail
1272472698
并且在 C:\ 生成文件:
1272472708
从上面的结果可知 sendmail.php 花费至少 10 秒,但不会阻塞到 write.php 的继续往下执行,表明这一过程是异步的。
参考:1. PHP多线程类
2. 浅析php中实现多线程
3. php实现多线程(实际是多进程,夸平台)
4. Using the POST method to read from a URL within a PHP script 永久链接 https://yanbin.blog/php-simulate-multithread/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。