ホームページ  >  記事  >  バックエンド開発  >  PHPマルチスレッドの実装方法を詳しく解説_PHPチュートリアル

PHPマルチスレッドの実装方法を詳しく解説_PHPチュートリアル

WBOY
WBOYオリジナル
2016-07-20 11:12:12844ブラウズ

Java ではマルチスレッド化は非常に良いことですが、PHP のマルチスレッド化は PHP では使用できないと多くの人が言いますが、実際には、PHP のマルチスレッド化の実装方法は fsockopen 関数に関連しています。さらに詳しく知りたい学生は参考にしてください。

同時実行機能を実装したいとき、通常、フォークまたは生成スレッドを使用することを考えますが、PHP がマルチスレッドをサポートしていないことがわかると、考えを変え、perl などの十分ではない言語を使用する可能性があります。
実際、ほとんどの場合、フォークやスレッドを使用する必要はなく、フォークやスレッドを使用するよりもパフォーマンスが向上します。
実行中のサーバーがまだ正常に機能していることを確認するサービスを構築するとします。次のようなコードを作成できます:

コードは次のとおりです コードをコピー

$hosts = array("host1.sample.com", "host2.sample.com") , "host3.sample.com");
$timeout = 15;
$status = array();
foreach ($hosts を $host) {
$errno = 0;
$errstr = "";
$s = fsockopen($host, 80, $errno, $errstr, $timeout);
if ($s) {
$status[$host] = "接続";
fwrite($s, "HEAD / HTTP/1.0rnHost : $hostrnrn");
do {
$data = fread($s, 8192);
if (strlen($data) == 0) {
Break;
}
$status[$host] .= $data ;
} while (true);
fclose($s);
} else {
$status[$host] = "接続に失敗しました: $errno $errstrn";
}
}
print_r($status);
? >

正常に動作しますが、このコードを拡張して多数のサーバーを管理するには、 fsockopen() がホスト名を解析して正常な接続を確立するまで (または $timeout 秒遅れて) 長い時間がかかります。
したがって、このコードを放棄する必要があります。fsockopen が接続ステータスを返すのを待つ必要がなく、非同期接続を確立できます。 PHP は依然としてホスト名を解決する必要があります (したがって、IP を直接使用する方が賢明です) が、接続を開いた後すぐにホスト名が返されるため、次のサーバーに接続できます。
これを実現するには 2 つの方法があります。PHP5 では、新しい stream_socket_client() 関数を使用して fsocketopen() を直接置き換えることができます。 PHP5 より前のバージョンの場合、問題を解決するには自分で実行し、ソケット拡張機能を使用する必要があります。
PHP5 での回避策は次のとおりです:
正常に動作しますが、このコードを拡張して多数のサーバーを管理するには、 fsockopen() がホスト名を解析し、正常な接続を確立する (または $timeout 秒を遅らせる) 時間がかかるまで、コストが高くなります。
したがって、このコードを放棄する必要があります。fsockopen が接続ステータスを返すのを待つ必要がなく、非同期接続を確立できます。 PHP は依然としてホスト名を解決する必要があります (したがって、IP を直接使用する方が賢明です) が、接続を開いた後すぐにホスト名が返されるため、次のサーバーに接続できます。
これを実現するには 2 つの方法があります。PHP5 では、新しい stream_socket_client() 関数を使用して fsocketopen() を直接置き換えることができます。 PHP5 より前のバージョンの場合、問題を解決するには自分で実行し、ソケット拡張機能を使用する必要があります。
以下は PHP5 での解決策です:

stream_select() を使用して、ソケットが開く接続イベントを待ちます。 stream_select() は、システムの select(2) 関数を呼び出して機能します。最初の 3 つのパラメータは、使用するストリームの配列であり、(3 つのパラメータごとに) 読み取り、書き込み、例外の取得が可能です。 stream_select() は、$timeout (秒) パラメータを設定することでイベントが発生するのを待つことができます。イベントが発生すると、渡したパラメータに対応するソケット データが書き込まれます。
以下は PHP 4.1.0 以降の実装です。PHP のコンパイル時にソケット (ext/sockets) サポートを組み込んでいる場合は、上記と同様のコードを使用できますが、ストリーム/ファイルシステムの関数には ext を使用する必要があります。上記の /sockets 関数の実装。主な違いは、接続を確立するために stream_socket_client() の代わりに次の関数を使用することです:

コードは次のとおりです コードをコピーします
$hosts = array("host1.sample.com", "host2.sample. com", " host3.sample.com");
$timeout = 15;
$status = array();
$sockets = array();
/* すべてのホストへの接続を同時に開始します */
foreach ($ $id => $host) {
$s = stream_socket_client("
$
$host:80", $errno, $errstr, $timeout,
STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
if ($s) {
$sockets[$ id] = $s;
$status[$id] = "進行中";
} else {
$status[$id] = "失敗しました、$errno $errstr";
}
}
/ * 次に、結果が戻ってくるのを待ちます */
while (count($sockets)) {
$read = $write = $sockets;
/* これは魔法の関数です - 以下で説明します */
$n = stream_select($read , $write, $e = null, $timeout);
if ($n > 0) {
/* 読み取り可能なソケットにデータがあるか、失敗しました
* 接続試行 */
foreach ( $read as $ r) {
$id = array_search($r, $sockets);
$data = fread($r, 8192);
if (strlen($data) == 0) {
「 progress") {
$status[$id] = "接続に失敗しました";
}
fclose($r);
unset($sockets[$id]);
$status[ $id] .= $data;
}
}
/* 書き込み可能なソケットは HTTP リクエストを受け入れることができます */
foreach ($write as $w) {
$id = array_search($w, $sockets);
fwrite( $w, "HEAD / HTTP/ 1.0rnHost: "
. $hosts[$id] . "rnrn");
$status[$id] = "応答待ち";
}
} else {
/* 待機中にタイムアウトしました; すべてのホストが関連付けられていると想定します
* $sockets には問題があります */
foreach ($sockets as $id => $s) {
$status[$id] = "タイムアウト " . $status[$id ];
}
Break;
}
}
foreach ($hosts as $id => $host) {
echo "ホスト: $hostn";
echo "ステータス: " . $status[$id] ;
}
?> ;

コードは次のとおりです コードをコピー
// この値は Linux では正しいです、他のシステムには他の値があります
define('EINPROGRESS', 115);
function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) {
$ip = gethostbyname($host);
$ s =socket_create(AF_INET, SOCK_STREAM, 0);
if (socket_set_nonblock($s)) {
$r = @socket_connect($s, $ip, $port);
if ($r ||ソケット_last_error() == EINPROGRESS) {
$errno = EINPROGRESS;
return $s;
}
}
$errno =ソケット_last_error($s);
$errstr =ソケット_strerror($errno);
ソケット_クローズ($s);
return false;
}
?>

ここで、stream_select() をsocket_select()、fread() をsocket_read()、fwrite() をsocket_write()、fclose() をsocket_close()に置き換えて、スクリプトを実行します。
PHP5 の進歩は、stream_select() を使用してほぼすべてのストリームを処理できることです。たとえば、これを使用して、STDIN をインクルードしてキーボード入力を受信し、配列に保存できます。また、開いたパイプからデータを受信することもできます。 proc_open() を通じて。

PHP マルチスレッド クラスを共有しましょう

代码如下 复制代

* @title: PHP多線程类(Thread)
* @version: 1.0
* @author: phper.org.cn < web@phper.org.cn >
* @published: 2010-11-2
*
* PHP多線程应用例:
* require_once 'thread.class.php';
* $thread = new thread();
* $thread->addthread('action_log','a');
* $thread->addthread('action_log','b');
* $thread->addthread('action_log',' c');
* $thread->runthread();
*
* function action_log($info) {
* $log = 'log/' . microtime() 。 '.log';
* $txt = $info 。 「ルンルン」 。 '始まる ' 。 Date('h:i:s', time()) 。 (double)microtime() 。 "rn";
* $fp = fopen($log, 'w');
* fwrite($fp, $txt);
* fclose($fp);
* }
*/
クラススレッド {

var $hooks = array();
var $args = array();

function thread() {
}

function addthread($func)
{
$args = array_slice(func_get_args(), 1);
$this->hooks[] = $func;
$this->args[] = $args;
return true;
}

function runthread()
{
if(isset($_GET['flag' ]))
{
$flag = intval($_GET['flag']);
}
if($flag || $flag === 0)
{
call_user_func _array($this->フック[$flag ], $this->args[$flag]);
}
else
{
for($i = 0, $size = count($this->hooks); $i {
$fp=fsockopen($_SERVER['HTTP_HOST'],$_SERVER['SERVER_PORT']);
if($fp)
{
$out = "{$_SERVER['PHP_SELF']}を取得しますか? flag=$i HTTP/1.1rn";
$out .= "ホスト: {$_SERVER['HTTP_HOST']}rn";
$out .= "接続: Closernrn";
fputs($fp,$out) ;
fclose($fp);
}
}
}
}
}


www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/444595.html技術記事 Java ではマルチスレッドは非常に良いことですが、PHP ではマルチスレッドを使用できないと多くの友人が言っていますが、実際には、PHP のマルチスレッドの実装方法は fsockopen 関数に関連しています。 ..
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。