IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [转]PHP 多线程的实现 curl_multi

    zhoubl668发表于 2014-09-16 17:12:16
    love 0

    大家都知道php没有多线程,这也是弱于java等高级语言的表现之一。

    但有时候我们还是需要php同时做一些操作,这时候我们可以借助服务器的多程线来实现。

    自然就会想起 curl_multi_* 系列函数,这些函数说明并不详细,例子也很少。

    一般来说,想到要用这些函数时,目的显然应该是要同时请求多个url,而不是一个一个依次请求。

    步骤总结如下:

    第一步:调用curl_multi_init
    第二步:循环调用curl_multi_add_handle
    这一步需要注意的是,curl_multi_add_handle的第二个参数是由curl_init而来的子handle。
    第三步:持续调用curl_multi_exec
    第四步:根据需要循环调用curl_multi_getcontent获取结果
    第五步:调用curl_multi_remove_handle,并为每个字handle调用curl_close
    第六步:调用curl_multi_close

    --------------------------- 以下例子为本人测试时使用 ----------------------------

    背景:

    1.在test数据库下建立test

    use test;

    CREATE TABLE `test` (
    `id` int(11) NOT NULL auto_increment,
    `record_date` datetime NOT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    2.在虚拟目录下建立相关测试目录和两个文件

    /www/test/curl_multi/index.php & do.php

    [php] view plaincopy
    1. /**
    2. * @Author: Ewing
    3. * @Date: 2010-10-10
    4. * @File:curl/multi/index.php
    5. * @Desc: make multi action
    6. */
    7. $t=getTime();
    8. $total=60;//由测试得少于64个线程运行一次没有延迟,太多的话可能是apache的原因,效果并不理想,大家可以自己输入不同的值测试
    9. for($i=0;$i<$total;$i++)
    10. $url_arr[]="http://localhost/test/curl_multi/do.php?i=$i";
    11. $mh = curl_multi_init();
    12. foreach ($url_arr as $i => $url) {
    13. $conn[$i]=curl_init($url);
    14. curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);//设置返回do.php页面输出内容
    15. curl_multi_add_handle ($mh,$conn[$i]);//添加线程
    16. }
    17. #----------------执行线程----------------
    18. //do { $n=curl_multi_exec($mh,$active); } while ($active); //网上说些方法有时会让CPU达100%
    19. do {
    20. $mrc = curl_multi_exec($mh,$active);
    21. } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    22. while ($active and $mrc == CURLM_OK) {
    23. if (curl_multi_select($mh) != -1) {
    24. do {
    25. $mrc = curl_multi_exec($mh, $active);
    26. } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    27. }
    28. }
    29. #-------------------------------
    30. foreach ($url_arr as $i => $url) {
    31. $res[$i]=curl_multi_getcontent($conn[$i]);//得到页面输入内容
    32. curl_close($conn[$i]);
    33. }
    34. foreach($res as $k=>$v){
    35. $k=str_pad($k,2,0);
    36. echo "$k => $v
      "
      ;
    37. }
    38. runTime($t);
    39. #----------- calculate time function-------------
    40. function getTime(){
    41. $TIME=explode(" ",microtime());
    42. $TIME=$TIME[1].substr($TIME[0],1);
    43. return $TIME;
    44. }
    45. function runTime($t,$l=3){
    46. $dif=getTime()-$t;
    47. echo ' '.number_format($dif,$l);
    48. }
    49. ?>

    [c-sharp] view plaincopy
    1. /**
    2. * @Author: Ewing
    3. * @Date: 2010-10-10
    4. * @File:curl/multi/do.php
    5. * @Desc: do something here
    6. */
    7. $t=getTime();
    8. sleep(mt_rand(1,3));//设置延迟
    9. //数据库处理
    10. mysql_connect("localhost","root","your_password");
    11. mysql_select_db("test");
    12. mysql_query("insert into test(record_date) value(NOW())");
    13. //文件处理
    14. $file='./test.txt';
    15. $fp=fopen($file,'a');
    16. flock($fp, LOCK_EX);
    17. fwrite($fp,date('H:i:s')."/n/r");
    18. fclose($fp);
    19. echo date('H:i:s');
    20. runTime($t);
    21. #-------------calculate time function------------
    22. function getTime(){
    23. $TIME=explode(" ",microtime());
    24. $TIME=$TIME[1].substr($TIME[0],1);
    25. return $TIME;
    26. }
    27. function runTime($t,$l=3){
    28. $dif=getTime()-$t;
    29. echo ' '.number_format($dif,$l);
    30. }
    31. ?>

    在浏览器上打开http://localhost/test/curl_multi/ 即可看到效果

    ps:以上例子只是用于本地处理多线程,用多线程取网页数据也是可以的,只要把index.php中的$url_arr换成外网的url即可。不过建议不要一次拿太多的url,不然会有意想不到的结果哦,想知道是什么?自己试试吧。





沪ICP备19023445号-2号
友情链接