[轉]通俗易懂的php多線程解決方案

來源:互聯網
上載者:User

標籤:就是   ble   code   mes   2.0   lis   exists   AC   lock   

原文: https://www.w3cschool.cn/php/php-thread.html

------------------------------------------------------------------通俗易懂的php多線程解決方案由 youj 建立,Carrie 最後一次修改 2016-12-01

我們在做項目的時候,有些需求,特別是資料的響應處理需要花費大量的時間,由於php是一個短生命週期的指令碼語言,到了預設的30秒,php的資料處理還沒完成,php的生命週期就結束了。這時需要使用非同步並發處理策略,也就是說,一次php調用可以發出的多個請求,這些請求不是按照順序執行,而是可以非同步並發執行的,一些請求用於在幕後處理資料,一些請求用於接受後台響應狀態,根據狀態,與使用者做一些簡單的互動。但是問題來了,我們都知道php本身是不支援多線程的,那麼應該怎麼實現php的多線程呢?

 

一、php類比實現多線程的三種方法

 

1、linux下的php多線程

下面所講的東西是源自php的pcntl_fork函數.因為這個函數依賴作業系統fork的實現,所以本文所講的東西只適用於linux/unix。那麼先看看這個函數的用法吧.php手冊上是這麼說的:

 

<?php$pid = pcntl_fork();if ($pid == -1) {         die(‘could not fork‘);} else if ($pid) {         // we are the parent         pcntl_wait($status); //Protect against Zombie children} else {         // we are the child}?>

 

通過pcntl_fork建立一個子進程,如果傳回值是-1的話,那麼說明子進程建立失敗.建立成功的進程id會返回給父進程,0返回給子進程.不好理解吧,所以應該這樣寫:

 

<?php$pid = pcntl_fork();if($pid == -1){         //建立失敗咱就退出唄,沒啥好說的         die(‘could not fork‘);}else{        if($pid){                //從這裡開始寫的代碼是父進程的,因為寫的是系統程式,記得退出的時候給個傳回值                exit(0);        }        else{                //從這裡開始寫的代碼都是在新的進程裡執行的,同樣正常退出的話,最好也給一個傳回值                exit(0);        }}?>
這樣一改好理解多了,如果你父進程希望知道子進程正常退出的話,可以加上前面的pcntl_wait。

 

 

2.通過stream_socket_client 方式

 

function sendStream() {     $english_format_number = number_format($number, 4, ‘.‘, ‘‘);       echo $english_format_number;      exit();     $timeout = 10;     $result = array();     $sockets = array();     $convenient_read_block = 8192;     $host = "test.local.com";     $sql = "select waybill_id,order_id from xm_waybill where status>40 order by update_time desc limit 1 ";      $data = Yii::app()->db->createCommand($sql)->queryAll();     $id = 0;       foreach ($data as $k => $v) {       if ($k % 2 == 0) {         $send_data[$k][‘body‘] = NoticeOrder::getSendData($v[‘waybill_id‘]);         } else {         $send_data[$k][‘body‘] = array($v[‘order_id‘] => array(‘extra‘ => 16));        }        $data = json_encode($send_data[$k][‘body‘]);       $s = stream_socket_client($host . ":80", $errno, $errstr, $timeout, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);       if ($s) {          $sockets[$id++] = $s;         $http_message = "GET /php/test.php?data=" . $data . " HTTP/1.0\r\nHost:" . $host . "\r\n\r\n";          fwrite($s, $http_message);       } else {          echo "Stream " . $id . " failed to open correctly.";       }      }       while (count($sockets)) {         $read = $sockets;         stream_select($read, $w = null, $e = null, $timeout);        if (count($read)) {          /* stream_select generally shuffles $read, so we need to          compute from which socket(s) we‘re reading. */        foreach ($read as $r) {             $id = array_search($r, $sockets);           $data = fread($r, $convenient_read_block);           if (strlen($data) == 0) {             echo "Stream " . $id . " closes at " . date(‘h:i:s‘) . ".<br>  ";             fclose($r);              unset($sockets[$id]);           } else {             $result[$id] = $data;           }         }       } else {          /* A time-out means that *all* streams have failed          to receive a response. */        echo "Time-out!\n";         break;       }      }      print_r($result);     }

 

3、通過多進程代替多線程

 

function daemon($func_name,$args,$number){   while(true){     $pid=pcntl_fork();     if($pid==-1){       echo "fork process fail";       exit();     }elseif($pid){//建立的子進程         static $num=0;       $num++;       if($num>=$number){         //當進程數量達到一定數量時候,就對子進程進行回收。         pcntl_wait($status);           $num--;       }      }else{ //為0 則代表是子進程建立的,則直接進入工作狀態         if(function_exists($func_name)){         while (true) {           $ppid=posix_getpid();           var_dump($ppid);           call_user_func_array($func_name,$args);           sleep(2);         }       }else{         echo "function is not exists";       }       exit();       }   } }  function worker($args){    //do something   }  daemon(‘worker‘,array(1),2); 

 

二、真正實現php多線程的方法php真正的多線程實現方式,通過安裝php的擴充 pthread 可以做到。

點此下載 但是這個下載的是 版本3 也就是php 7 才能用的,我們需要使的是 版本2 

然後重新整理的頁面如下,拖到最底部:
 

下一頁找到版本2的

下載下來,這個v2 才是php5才可以使用的

下載下來,安裝:

或者,您直接這樣下載:

cd /tools     wget https://github.com/krakjoe/pthreads/archive/v2.0.10.zip     unzip   v2.0.10.zip     cd pthreads-2.0.10     /usr/local/php/bin/phpize     ./configure --with-php-config=/usr/local/php/bin/php-config       make     make install
注意:您的php 在編譯的時候需要開啟 –enable-maintainer-zts
./configure --prefix=/usr/local/php --disable-fileinfo   --enable-fpm --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-openssl --with-zlib --with-curl --enable-ftp --with-gd --with-xmlrpc  --with-jpeg-dir --with-png-dir --with-freetype-dir --enable-gd-native-ttf --enable-mbstring --with-mcrypt=/usr/local/libmcrypt --enable-zip --with-mysql=/usr/local/mysql --without-pear --enable-maintainer-zts 
vim /etc/php.ini 添加extension=pthreads.so
重啟php  /etc/init.d/php-fpm restart

[轉]通俗易懂的php多線程解決方案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.