当前位置:Gxlcms > PHP教程 > php三种实现多线程类似的方法_php技巧

php三种实现多线程类似的方法_php技巧

时间:2021-07-01 10:21:17 帮助过:47人阅读

1、curl_multi方法

当需要多线程的时候,可以用curl_multi一次性请求多个操作来完成,但curl走的是网络通信,效率与可靠性就比较差了的。

  1. function main(){
  2. $sql = "select waybill_id,order_id from waybill where status>40 order by update_time desc limit 10 ";
  3. $data = Yii::app()->db->createCommand($sql)->queryAll(); //yii 框架格式
  4. foreach ($data as $k => $v) {
  5. if ($k % 2 == 0) { //偶数发一个网址
  6. $send_data[$k]['url'] = '';
  7. $send_data[$k]['body'] = $v['waybill_id'];
  8. } else { //奇数发送另外一个网址
  9. $send_data[$k]['url'] = 'http://www.abc.com';
  10. $send_data[$k]['body']=array($v['order_id'] => array('extra' => 16));
  11. }
  12. }
  13. $back_data =sendMulitRequest($send_data);
  14. var_dump($back_data);
  15. }
  16. function sendMulitRequest($send_data){
  17. $params = array();
  18. $curl = $text = array();
  19. $handle = curl_multi_init();
  20. foreach ($data as $k => $v) {
  21. if (empty($v['url'])) {
  22. $v['url'] = "http://www.xxx.com"; //if url is empty,set defalut url
  23. }
  24. $reqBody = json_encode($v['body']);
  25. $reqStream = array(
  26. 'body' => $reqBody,
  27. );
  28. $encRequest = base64_encode(json_encode($reqStream));
  29. $params['data'] = $encRequest;
  30. $curl[$k] = curl_init();
  31. curl_setopt($curl[$k], CURLOPT_URL, $v['url']);
  32. curl_setopt($curl[$k], CURLOPT_POST, TRUE);
  33. curl_setopt($curl[$k], CURLOPT_HEADER, 0);
  34. curl_setopt($curl[$k], CURLOPT_POSTFIELDS, http_build_query($params));
  35. curl_setopt($curl[$k], CURLOPT_RETURNTRANSFER, 1);
  36. curl_multi_add_handle($handle, $curl[$k]);
  37. }
  38. $active = null;
  39. do {
  40. $mrc = curl_multi_exec($handle, $active);
  41. } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  42. while ($active && $mrc == CURLM_OK) {
  43. if (curl_multi_select($handle) != -1) {
  44. do {
  45. $mrc = curl_multi_exec($handle, $active);
  46. } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  47. }
  48. }
  49. foreach ($curl as $k => $v) {
  50. if (curl_error($curl[$k]) == "") {
  51. $text[$k] = (string) curl_multi_getcontent($curl[$k]);
  52. }
  53. curl_multi_remove_handle($handle, $curl[$k]);
  54. curl_close($curl[$k]);
  55. }
  56. curl_multi_close($handle);
  57. return $text;
  58. }

2、通过stream_socket_client 方式

  1. function sendStream() {
  2. $english_format_number = number_format($number, 4, '.', '');
  3. echo $english_format_number;
  4. exit();
  5. $timeout = 10;
  6. $result = array();
  7. $sockets = array();
  8. $convenient_read_block = 8192;
  9. $host = "test.local.com";
  10. $sql = "select waybill_id,order_id from xm_waybill where status>40 order by update_time desc limit 1 ";
  11. $data = Yii::app()->db->createCommand($sql)->queryAll();
  12. $id = 0;
  13. foreach ($data as $k => $v) {
  14. if ($k % 2 == 0) {
  15. $send_data[$k]['body'] = NoticeOrder::getSendData($v['waybill_id']);
  16. } else {
  17. $send_data[$k]['body'] = array($v['order_id'] => array('extra' => 16));
  18. }
  19. $data = json_encode($send_data[$k]['body']);
  20. $s = stream_socket_client($host . ":80", $errno, $errstr, $timeout, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);
  21. if ($s) {
  22. $sockets[$id++] = $s;
  23. $http_message = "GET /php/test.php?data=" . $data . " HTTP/1.0\r\nHost:" . $host . "\r\n\r\n";
  24. fwrite($s, $http_message);
  25. } else {
  26. echo "Stream " . $id . " failed to open correctly.";
  27. }
  28. }
  29. while (count($sockets)) {
  30. $read = $sockets;
  31. stream_select($read, $w = null, $e = null, $timeout);
  32. if (count($read)) {
  33. /* stream_select generally shuffles $read, so we need to
  34. compute from which socket(s) we're reading. */
  35. foreach ($read as $r) {
  36. $id = array_search($r, $sockets);
  37. $data = fread($r, $convenient_read_block);
  38. if (strlen($data) == 0) {
  39. echo "Stream " . $id . " closes at " . date('h:i:s') . ".<br> ";
  40. fclose($r);
  41. unset($sockets[$id]);
  42. } else {
  43. $result[$id] = $data;
  44. }
  45. }
  46. } else {
  47. /* A time-out means that *all* streams have failed
  48. to receive a response. */
  49. echo "Time-out!\n";
  50. break;
  51. }
  52. }
  53. print_r($result);
  54. }

3、通过多进程代替多线程

  1. function daemon($func_name,$args,$number){
  2. while(true){
  3. $pid=pcntl_fork();
  4. if($pid==-1){
  5. echo "fork process fail";
  6. exit();
  7. }elseif($pid){//创建的子进程
  8. static $num=0;
  9. $num++;
  10. if($num>=$number){
  11. //当进程数量达到一定数量时候,就对子进程进行回收。
  12. pcntl_wait($status);
  13. $num--;
  14. }
  15. }else{ //为0 则代表是子进程创建的,则直接进入工作状态
  16. if(function_exists($func_name)){
  17. while (true) {
  18. $ppid=posix_getpid();
  19. var_dump($ppid);
  20. call_user_func_array($func_name,$args);
  21. sleep(2);
  22. }
  23. }else{
  24. echo "function is not exists";
  25. }
  26. exit();
  27. }
  28. }
  29. }
  30. function worker($args){
  31. //do something
  32. }
  33. daemon('worker',array(1),2);

以上就是为大家分享的三种php实现多线程类似的方法,希望对大家的学习有所帮助。

人气教程排行