日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

用 PHP V5 開發(fā)多任務(wù)應(yīng)用程序

瀏覽:31日期:2024-02-15 15:29:46

許多 PHP 開發(fā)人員認(rèn)為,由于標(biāo)準(zhǔn)的 PHP 缺少線程功能,因此實(shí)際 PHP 應(yīng)用程序不可能執(zhí)行多任務(wù)處理。例如,如果應(yīng)用程序需要其他 Web 站點(diǎn)的信息,那么在遠(yuǎn)程檢索完成之前它都必須停止。這是錯(cuò)誤的!通過本文了解如何使用 stream_select 和 stream_socket_client 實(shí)現(xiàn)進(jìn)程內(nèi) PHP 多任務(wù)處理。

PHP 不支持線程。盡管如此,與前述大多數(shù) PHP 開發(fā)人員所相信的想法形成對比的是,PHP 應(yīng)用程序可以 執(zhí)行多任務(wù)處理。讓我們開始盡可能清晰地描述一下 “多任務(wù)” 和 “線程” 對于 PHP 編程的意義。

并發(fā)的種類

首先拋開幾個(gè)和主題無關(guān)的例子。PHP 與多任務(wù)或并發(fā)的關(guān)系十分復(fù)雜。在較高層次上,PHP 經(jīng)常涉及多任務(wù):以多任務(wù)方式使用 標(biāo)準(zhǔn)的服務(wù)器端 PHP 安裝 —— 例如,作為 Apache 模塊。換句話說,若干個(gè)客戶機(jī) —— Web 瀏覽器 —— 可以同時(shí)請求同一個(gè) PHP 解釋的頁面,而 Web 服務(wù)器將差不多同時(shí)返回所有這些頁面。

一個(gè) Web 頁面不會(huì)妨礙其他 Web 頁面的發(fā)送,盡管可能會(huì)由于諸如服務(wù)器內(nèi)存或網(wǎng)絡(luò)帶寬之類的受限資源而使它們相互之間略有妨礙。這樣,實(shí)現(xiàn)并發(fā) 的系統(tǒng)級需求可能適合使用基于 PHP 的解決方案。就實(shí)現(xiàn)而言,PHP 允許它的管理 Web 服務(wù)器負(fù)責(zé)實(shí)現(xiàn)并發(fā)。

Ajax 名下的客戶端并發(fā)近幾年來也已成為開發(fā)人員關(guān)注的焦點(diǎn)。雖然 Ajax 的含義已經(jīng)變得十分模糊,但是它的一個(gè)方面是瀏覽器顯示可以同時(shí)執(zhí)行計(jì)算和 保留對諸如選擇菜單項(xiàng)之類的用戶操作的響應(yīng)。這實(shí)際上就是某種 多任務(wù)。用 PHP 編碼的 Ajax 就是這樣 —— 但是不涉及任何特定的 PHP;用于其他語言的 Ajax 框架均以完全相同的方法操作。

只粗略地涉及 PHP 的第三個(gè)并發(fā)實(shí)例是 PHP/TK。PHP/TK 是 PHP 的擴(kuò)展,用于為核心 PHP 提供可移植圖形用戶界面(GUI)綁定。PHP/TK 允許用 PHP 編寫代碼構(gòu)造桌面 GUI 應(yīng)用程序。其基于事件的特性將模擬一種易于掌握并且比線程更少出錯(cuò)的并發(fā)形式。此外,并發(fā)是 “繼承” 自一項(xiàng)輔助技術(shù),而不是 PHP 的基本功能。

向 PHP 本身添加線程支持的試驗(yàn)已經(jīng)做過多次。據(jù)我所知,沒有一次是成功的。但是,Ajax 框架和 PHP/TK 的面向事件的實(shí)現(xiàn)表明事件可能比線程能更好地體現(xiàn) PHP 的并發(fā)。PHP V5 證明事實(shí)確實(shí)如此。

PHP V5 將提供 stream_select()

使用標(biāo)準(zhǔn)的 PHP V4 和更低版本,必須按順序執(zhí)行 PHP 應(yīng)用程序的所有工作。例如,如果程序需要在兩個(gè)商業(yè)站點(diǎn)檢索商品的價(jià)格,則請求第一個(gè)站點(diǎn)的價(jià)格,等待至響應(yīng)到達(dá),再請求第二個(gè)站點(diǎn)的價(jià)格,然后再次等待。

如果程序請求同時(shí)完成若干項(xiàng)任務(wù)會(huì)怎么樣?總體來看,程序?qū)⒃谝欢螘r(shí)間內(nèi)完成,在這段時(shí)間內(nèi),將始終進(jìn)行連續(xù)處理。

第一個(gè)示例

新的 stream_select 函數(shù)及它的幾個(gè)助手使這成為可能。請考慮以下示例。

清單 1. 同時(shí)請求多個(gè) HTTP 頁面

<?phpecho 'Program starts at '. date('h:i:s') . '.n';

$timeout=10; $result=array(); $sockets=array(); $convenient_read_block=8192;

/* Issue all requests simultaneously; there's no blocking. */$delay=15;$id=0;while ($delay > 0) { $s=stream_socket_client('phaseit.net:80', $errno,$errstr, $timeout,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);  if ($s) { $sockets[$id++]=$s; $http_message='GET /demonstration/delay?delay=' . $delay . ' HTTP/1.0rnHost: phaseit.netrnrn'; fwrite($s, $http_message); } else { echo 'Stream ' . $id . ' failed to open correctly.'; }  $delay -= 3;}

while (count($sockets)) {  $read=$sockets;  stream_select($read, $w=null, $e=null, $timeout);  if (count($read)) {/* stream_select generally shuffles $read, so we need tocompute from which socket(s) we're reading. */foreach ($read as $r) {  $id=array_search($r, $sockets);  $data=fread($r, $convenient_read_block);  /* A socket is readable either because it has data to read, OR because it's at EOF. */ if (strlen($data) == 0) { echo 'Stream ' . $id . ' closes at ' . date('h:i:s') . '.n';fclose($r); unset($sockets[$id]);  } else { $result[$id] .= $data;  } }  } else { /* A time-out means that *all* streams have failedto receive a response. */echo 'Time-out!n';break; } } ?>

如果運(yùn)行此清單,您將看到如下所示的輸出。

清單 2. 從清單 1 中的程序獲得的典型輸出

Program starts at 02:38:50.Stream 4 closes at 02:38:53.Stream 3 closes at 02:38:56.Stream 2 closes at 02:38:59.Stream 1 closes at 02:39:02.Stream 0 closes at 02:39:05.

了解這其中的工作原理至關(guān)重要。在較高層次上,第一個(gè)程序?qū)l(fā)出幾個(gè) HTTP 請求并接收 Web 服務(wù)器發(fā)送給它的頁面。雖然生產(chǎn)應(yīng)用程序?qū)⒑芸赡軐ふ胰舾蓚€(gè) Web 服務(wù)器的地址 —— 可能是 google.com、yahoo.com、ask.com 等 —— 但是此示例將把它的所有請求發(fā)送到位于 Phaseit.net 的企業(yè)服務(wù)器上,只為降低復(fù)雜度。

Web 頁面請求在延遲(可變)后返回結(jié)果,如下所示。如果程序按順序發(fā)出請求,則需花費(fèi)大約 15+12+9+6+3 (45) 秒鐘才能完成。如清單 2 所示,它實(shí)際上花費(fèi) 15 秒鐘完成。性能提高了三倍。

使這成為可能的是 PHP V5 的新 stream_select 函數(shù)。請求都是以常規(guī)方法發(fā)起,方法為打開幾個(gè) stream_socket_client 并向?qū)?yīng)于 http://phaseit.net/demonstration/delay?delay=$DELAY 的每個(gè) stream_socket_client 寫入 GET。如果您通過瀏覽器請求此 URL,則在幾秒鐘之后,您將看到:

Starting at Thu Apr 12 15:05:01 UTC 2007. Stopping at Thu Apr 12 15:05:05 UTC 2007. 4 second delay.

延遲服務(wù)器將作為 CGI 實(shí)現(xiàn),如下所示:

清單 3. 延遲服務(wù)器實(shí)現(xiàn)

#!/bin/sh

echo 'Content-type: text/html

<HTML> <HEAD></HEAD> <BODY>'

echo 'Starting at `date`.'RR=`echo $REQUEST_URI | sed -e 's/.*?//'`DELAY=`echo $RR | sed -e 's/delay=//'`sleep $DELAYecho '<br>Stopping at `date`.'echo '<br>$DELAY second delay.</body></html>'

雖然清單 3 的特殊實(shí)現(xiàn)特定于 UNIX?,但是本文中幾乎所有實(shí)現(xiàn)都將很好地應(yīng)用于 Windows?(尤其是 Windows 98 以后的版本)或 PHP 的 UNIX 安裝。特別地,清單 1 可以托管在任意一個(gè)操作系統(tǒng)中。因此,Linux? 和 Mac OS X 都是 UNIX 變體,因此這里所有的代碼都可以在兩者的任意一種中運(yùn)行。

按照以下順序向延遲服務(wù)器發(fā)出請求。

清單 4. 進(jìn)程啟動(dòng)順序

delay=15delay=12delay= 9delay= 6delay= 3

stream_select 的作用是盡可能快速地接收結(jié)果。在這種情況下,它執(zhí)行的順序與發(fā)出結(jié)果的順序剛好相反。3 秒后,第一個(gè)頁面已經(jīng)準(zhǔn)備好讀取。程序的這一部分也符合常規(guī) PHP —— 在本例中,使用 fread。就像在其他 PHP 程序一樣,讀取可以很好地通過 fgets 完成。

處理將以同樣的方法繼續(xù)。程序?qū)⒃?stream_select 停止,直至數(shù)據(jù)就緒。重要的一點(diǎn)是,只要任何 連接具有數(shù)據(jù),不管順序怎樣,程序都將開始讀取。這是程序進(jìn)行多任務(wù)處理或并發(fā)處理來自多個(gè)請求的結(jié)果的方法。

注意,這沒有對主機(jī) CPU 造成任何負(fù)擔(dān)。經(jīng)常會(huì)遇到這樣一些連網(wǎng)程序,以 CPU 使用率急速上升至 100% 的方式在 while 中使用 fread。那種情況不會(huì)出現(xiàn)在這里,因?yàn)?stream_select 擁有支持立即響應(yīng)所需的屬性(只要有任何讀取信息),但是它將在各讀取操作間隙的等待時(shí)間內(nèi)產(chǎn)生可忽略的 CPU 負(fù)載。

必備的 stream_select() 知識(shí)

諸如此類的基于事件的編程并不是最基本的。雖然清單 1 被簡化到只包含最基本要素,但是涉及作為多任務(wù)應(yīng)用程序必要元素的回調(diào)或協(xié)調(diào)的任何編碼,比簡單的程序順序更讓人覺得陌生。在這種情況下,大多數(shù)挑戰(zhàn)集中在 $read 數(shù)組上。注意,它是一個(gè)引用;stream_select 將通過改變 $read 的內(nèi)容返回重要信息。就像指針是 C 的最大絆腳石一樣,引用似乎是 PHP 中最讓程序員感到棘手的一部分。

您可以使用這項(xiàng)技術(shù)向任意個(gè)外部 Web 站點(diǎn)發(fā)出請求,確信您的程序會(huì)盡快收到所有結(jié)果,而無需等待其他請求。實(shí)際上,該技術(shù)將正確處理所有 TCP/IP 連接,而不只是 Web 端口 80 上的連接,因此您可以大體上管理 LDAP 檢索、SMTP 傳輸、SOAP 請求等。

但那不是全部。PHP V5 將管理 “流” 之類的各種連接,而不僅是簡單的套接字。PHP 的 Client URL library (CURL) 支持 HTTPS 證書、FTP 上傳、cookie 等。(CURL 允許 PHP 應(yīng)用程序使用各種協(xié)議連接至服務(wù)器)。由于 CURL 將提供流接口,因此從程序的角度來看,連接是透明的。下一個(gè)部分將展示 stream_select 如何多路傳輸本地計(jì)算。

對于 stream_select 還有幾點(diǎn)需要注意。它還在進(jìn)行文檔整理,因?yàn)榧词棺钚碌?PHP 書籍都沒有涉列它。可在 Web 上獲得的幾個(gè)代碼示例完全不能工作或者讓人產(chǎn)生混淆。stream_select 的第二個(gè)和第三個(gè)參數(shù)用于管理與清單 1 的 read 通道相對應(yīng)的 write 和 exception 通道,應(yīng)當(dāng)始終為 null。除了少數(shù)例外情況,在可寫通道或異常通道中選擇這兩個(gè)參數(shù)是錯(cuò)誤的。除非您有經(jīng)驗(yàn),否則請堅(jiān)持可讀選擇。

此外,至少在 PHP V5.1.2 之前,stream_select 還明顯存在錯(cuò)誤。最重要的是,不能信任函數(shù)的返回值。雖然我尚未調(diào)試過實(shí)現(xiàn),但是經(jīng)驗(yàn)告訴我,可以安全地測試清單 1 中的 count($read),但是測試 stream_select 本身的返回值并不 安全(盡管有官方文檔)。

本地 PHP 并發(fā)

示例及上面的大部分討論主要討論了如何同時(shí)管理若干個(gè)遠(yuǎn)程資源并接收到達(dá)的結(jié)果,而不是按照最初請求的順序等待處理各個(gè)請求。這肯定是 PHP 并發(fā)的重要應(yīng)用。實(shí)際應(yīng)用程序的速度有時(shí)候可以提高 10 倍或更多。

如果出現(xiàn)性能衰退怎么辦?有沒有一種方法可以提升受限于本地處理的 PHP 結(jié)果的速度?方法有多種。要說有什么不同的話,這些方法不如清單 1 中的面向套接字的方法有名。造成這種情況的原因有很多,包括:

大多數(shù) PHP 頁面已經(jīng)足夠快 —— 更好的性能會(huì)是一種優(yōu)勢,但是還不值得對新代碼進(jìn)行投入。 在 Web 頁面中使用 PHP 可以放棄部分無關(guān)緊要的性能提升 —— 當(dāng)惟一的價(jià)值標(biāo)準(zhǔn)是交付整個(gè) Web 頁面需要的時(shí)間時(shí),那么重新安排計(jì)算以更快地獲得中間結(jié)果并不重要。

PHP 不能控制本地瓶頸 —— 用戶可能會(huì)為花 8 秒的時(shí)間提取帳戶記錄的詳細(xì)信息而抱怨,但是那很可能是數(shù)據(jù)庫處理或某種其他 PHP 外部資源的約束。即使將 PHP 處理降至零,單是查找就仍需要花費(fèi)超過 7 秒的時(shí)間。

甚至很少有約束是并行的 —— 假定某特定頁面將為具體列出的普通股計(jì)算建議交易價(jià)格,并且計(jì)算十分復(fù)雜,需要花費(fèi)一段時(shí)間。計(jì)算在本質(zhì)上可能是順序執(zhí)行的。沒有一種明顯的方法可以將其劃分為 “團(tuán)隊(duì)協(xié)作”。

很少有 PHP 程序員能夠認(rèn)識(shí)到 PHP 實(shí)現(xiàn)并發(fā)的潛力。在具有使用并行實(shí)現(xiàn)性能需求的少數(shù)人當(dāng)中,我遇到的大多數(shù)人全都說 PHP “不支持線程”,并且甘于使用現(xiàn)有的計(jì)算模型。

可是,有時(shí)我們可以做得更好。假定 PHP 頁面需要計(jì)算兩只股票價(jià)格,可能還需要將兩者相比較,并且底層主機(jī)剛好是多處理器。在這種情況下,通過將兩個(gè)截然不同并且十分耗時(shí)的計(jì)算分配給不同處理器,可能會(huì)提高幾乎兩倍的性能。

在所有 PHP 計(jì)算領(lǐng)域中,此類實(shí)例很少見。但是,由于我發(fā)現(xiàn)到處都沒有對它的精確記錄,因此需要在這里包括用于此類加速的模型。

清單 5. 延遲服務(wù)器實(shí)現(xiàn)

<?phpecho 'Program starts at '. date('h:i:s') . '.n';

$timeout=10; $streams=array();$handles=array();

/* First launch a program with a delay of three seconds, thenone which returns after only one second. */$delay=3;for ($id=0; $id <= 1; $id++) { $error_log='/tmp/error' . $id . '.txt' $descriptorspec=array(0 => array('pipe', 'r'),1 => array('pipe', 'w'),2 => array('file', $error_log, 'w') ); $cmd='sleep ' . $delay . '; echo 'Finished with delay of ' . $delay . ''.'; $handles[$id]=proc_open($cmd, $descriptorspec, $pipes); $streams[$id]=$pipes[1]; $all_pipes[$id]=$pipes; $delay -= 2;}

while (count($streams)) {  $read=$streams;  stream_select($read, $w=null, $e=null, $timeout);  foreach ($read as $r) { $id=array_search($r, $strea**ms); echo stream_get_contents($all_pipes[$id][1]);if (feof($r)) { fclose($all_pipes[$id][0]); fclose($all_pipes[$id][1]); $return_value=proc_close($handles[$id]); unset($streams[$id]); } } } ?>

此程序?qū)⑸扇缦螺敵觯?/P>

Program starts at 10:28:41.Finished with delay of 1.Finished with delay of 3.

這里的關(guān)鍵在于 PHP 啟動(dòng)了兩個(gè)獨(dú)立子進(jìn)程,取回待完成的第一個(gè)進(jìn)程的輸出,然后取回第二個(gè)進(jìn)程的輸出,即使后者啟動(dòng)得較早。如果主機(jī)是多處理器計(jì)算機(jī),并且操作系統(tǒng)已正確配置,則操作系統(tǒng)本身負(fù)責(zé)將各個(gè)子程序分配給不同的處理器。這是在多處理器主機(jī)中良好應(yīng)用 PHP 的一種方法。

PHP 支持多任務(wù)。PHP 不按照諸如 Java 編程語言或 C++ 等其他語言所采用的方法支持線程,但是以上示例表明 PHP 具有更多的超乎想象的加速潛力。

標(biāo)簽: PHP
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
麻豆亚洲精品| 亚洲一卡久久| 国产欧美日韩精品一区二区免费| 99视频在线精品国自产拍免费观看| 国产精品蜜月aⅴ在线| 日韩视频精品在线观看| 国产成人免费精品| 国产精品久久乐| 亚洲日韩中文字幕一区| 亚洲欧美一级| 久久亚洲欧美| 欧美搞黄网站| 牛牛精品成人免费视频| 亚洲伦乱视频| 日韩精品欧美成人高清一区二区| 日韩一级欧洲| 久久电影一区| 嫩草伊人久久精品少妇av杨幂| 日韩国产成人精品| 日韩av不卡在线观看| 性欧美精品高清| 亚洲精品影视| 亚洲成人精品| 影视先锋久久| 国产精品亚洲欧美| 国产精品mm| 国产乱子精品一区二区在线观看 | 国产精品国产三级国产在线观看| 亚洲午夜一级| 日韩avvvv在线播放| 在线精品一区| 日韩一区二区三区四区五区| 噜噜噜久久亚洲精品国产品小说| 中文在线不卡| 你懂的国产精品| 亚洲成人一区| 国产一区清纯| 天堂精品久久久久| 国产亚洲福利| 美女精品久久| 国产亚洲电影| 精品国产亚洲一区二区三区大结局| 裤袜国产欧美精品一区| 精品视频高潮| 国产v综合v| 蜜桃av一区二区| 亚洲韩日在线| 伊人网在线播放| 久久精品卡一| 国产成人精品三级高清久久91| 婷婷成人基地| 精品丝袜在线| 精品国产午夜| 国产精品极品在线观看| 欧美亚洲国产激情| 国产精品亚洲综合色区韩国| 亚洲日本欧美| 精品国产不卡| 麻豆视频在线观看免费网站黄| 亚洲一级网站| 视频精品一区二区| 天堂久久av| 亚洲成人av观看| 日韩在线a电影| 精品亚洲精品| 尤物在线精品| 中文在线а√在线8| 精品视频久久| 国产精品蜜芽在线观看| 日韩在线第七页| 精精国产xxxx视频在线播放| 亚洲伊人av| 国产精品一区二区三区美女| 亚洲高清av| 精品国产亚洲一区二区三区| 九九久久婷婷| 国产精久久久| 欧美午夜三级| 国产精品毛片| 婷婷亚洲综合| 欧美成人一二区| 国产探花在线精品| 日韩区一区二| 欧洲毛片在线视频免费观看| 国产精品白丝久久av网站| 色狠狠一区二区三区| 亚洲欧洲一区| 99久久精品网站| 国产美女高潮在线观看| 国产精品毛片久久| 久久久久久自在自线| 精品九九在线| 国产一区二区三区四区二区| 久久精品亚洲人成影院| 天堂成人国产精品一区| 国产精品久久777777毛茸茸| 日韩精品电影| 国产伦理一区| 久久国产精品亚洲77777| 精品国产亚洲一区二区在线观看| 日本久久综合| 日韩亚洲国产欧美| 日av在线不卡| 最新国产精品| 美女尤物久久精品| 欧美亚洲国产日韩| 在线综合亚洲| 久久香蕉精品香蕉| 亚洲精选久久| av免费不卡国产观看| 伊人久久亚洲| 男人天堂欧美日韩| 九九99久久精品在免费线bt| 婷婷国产精品| 日韩精品亚洲一区二区三区免费| 麻豆国产欧美日韩综合精品二区| 欧美亚洲自偷自偷| 国产精品综合色区在线观看| 黄在线观看免费网站ktv| 先锋亚洲精品| 国产精品毛片久久久| 性欧美69xoxoxoxo| 精品久久久网| 激情欧美亚洲| 激情综合网址| 亚洲一区二区三区高清| 麻豆成人综合网| 国产精品最新| 国产精品美女在线观看直播| 亚洲一区二区网站| 中文亚洲欧美| 国产主播一区| av资源中文在线天堂| 欧美中文一区二区| 久久狠狠久久| 免费日韩视频| 欧美一区二区性| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 天堂资源在线亚洲| 欧美日韩四区| 国产aa精品| 日韩中文字幕高清在线观看| 玖玖玖国产精品| 国产精品腿扒开做爽爽爽挤奶网站| 欧美日韩91| 国产亚洲一区二区三区不卡| 欧美久久亚洲| 自拍自偷一区二区三区| 日韩不卡视频在线观看| 另类欧美日韩国产在线| 日韩黄色av| 青青久久av| 亚洲三级av| 日本va欧美va精品| 麻豆国产一区| 欧美精品第一区| 久久精品123| 日韩av影院| 91精品一区二区三区综合在线爱| 久久男人天堂| 国产视频一区三区| 不卡福利视频| 国产精品丝袜在线播放| 美国三级日本三级久久99 | 国产九一精品| 成人污污视频| 黄色成人精品网站| 日韩高清中文字幕一区| 日本欧美国产| 午夜在线精品| 免费在线亚洲| 亚洲电影在线| 日韩av网站在线免费观看| 国产精品蜜芽在线观看| 国产美女一区| 久久精品国产亚洲一区二区三区| 欧美日中文字幕| 日韩高清在线观看一区二区| 国产欧美精品久久| 丰满少妇一区| 制服诱惑一区二区| 国产精品videosex极品| 欧美永久精品| 国产日韩欧美三区| 日韩成人精品一区| 精品国产美女a久久9999| 欧美日韩在线精品一区二区三区激情综合 | 欧美精品一区二区久久| 麻豆国产欧美一区二区三区 | 国产精品嫩草影院在线看| 亚洲精品无吗| 欧美激情日韩| 亚洲一本视频| 国产午夜精品一区在线观看| 色婷婷色综合| 亚洲一区二区毛片| 国产色综合网| 久久免费高清| 国产伦一区二区三区| 欧美福利一区|