更新时间:2016年10月14日 11:44:25 作者:新闻
多线程在Java中是一个非常好的东西。 很多朋友说PHP中不能使用PHP多线程。 事实上,这是一个错误的说法。 本文介绍PHP中多线程的两种实现方法。 有兴趣的同学可以看一下。
PHP本身是否支持多线程,但是我们可以使用其他方法来实现多线程,比如shell服务,比如web服务器。 在这篇文章中,我们将讨论如何实现这两种方法。 有需要的朋友可以过来参考一下。
多线程在Java中是一个非常好的东西。 很多朋友说PHP中不能使用PHP多线程。 事实上,这是一个错误的说法。 PHP多线程的实现方法与函数有关。 下面介绍一下具体的实现程序代码。 需要了解更多的同学可以参考一下。
当有人想要实现并发功能时,通常会想到使用fork或spawn,但是当他们发现PHP不支持多线程时,他们可能会改变主意并使用一些不够好的语言,例如perl。
事实是,在大多数情况下,您不需要使用 fork 或线程,并且会获得比使用 fork 或线程更好的性能。
假设您要构建一个服务来检查 n 个正在运行的服务器,以确保它们仍然正常运行。 你可能会编写这样的代码:
代码如下所示:
<?php $hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com"); $timeout = 15; $status = array(); foreach ($hosts as $host) { $errno = 0; $errstr = ""; $s = fsockopen($host, 80, $errno, $errstr, $timeout); if ($s) { $status[$host] = "Connectedn"; 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] = "Connection failed: $errno $errstrn"; } } print_r($status); ?>
它工作得很好,但是扩展此代码以管理大量服务器将需要很长时间才能分析 () 并建立成功的连接(或延迟 $ 秒)。
所以我们必须放弃这段代码; 我们可以建立异步连接——无需等待连接状态返回。 PHP仍然需要解析(所以直接使用IP更明智),但是打开连接后它会立即返回,然后我们可以连接到下一个服务器。
有两种方法可以实现这一目标; 在PHP5中,可以使用new()函数直接替换()。 PHP5之前的版本,需要自己动手,使用扩展来解决问题。
PHP5中的解决方案如下:
它工作得很好,但是扩展此代码以管理大量服务器将需要很长时间才能分析 () 并建立成功的连接(或延迟 $ 秒)。
所以我们必须放弃这段代码; 我们可以建立异步连接——无需等待连接状态返回。 PHP仍然需要解析(所以直接使用IP更明智),但是打开连接后它会立即返回,然后我们可以连接到下一个服务器。
有两种方法可以实现这一目标; 在PHP5中,可以使用new()函数直接替换()。 PHP5之前的版本,需要自己动手,使用扩展来解决问题。
代码如下所示:
<?php $hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com"); $timeout = 15; $status = array(); $sockets = array(); /* Initiate connections to all the hosts simultaneously */ foreach ($hosts as $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] = "in progress"; } else { $status[$id] = "failed, $errno $errstr"; } } /* Now, wait for the results to come back in */ while (count($sockets)) { $read = $write = $sockets; /* This is the magic function - explained below */ $n = stream_select($read, $write, $e = null, $timeout); if ($n > 0) { /* readable sockets either have data for us, or are failed * connection attempts */ foreach ($read as $r) { $id = array_search($r, $sockets); $data = fread($r, 8192); if (strlen($data) == 0) { if ($status[$id] == "in progress") { $status[$id] = "failed to connect"; } fclose($r); unset($sockets[$id]); } else { $status[$id] .= $data; } } /* writeable sockets can accept an HTTP request */ foreach ($write as $w) { $id = array_search($w, $sockets); fwrite($w, "HEAD / HTTP/1.0rnHost: " . $hosts[$id] . "rnrn"); $status[$id] = "waiting for response"; } } else { /* timed out waiting; assume that all hosts associated * with $sockets are faulty */ foreach ($sockets as $id => $s) { $status[$id] = "timed out " . $status[$id]; } break; } } foreach ($hosts as $id => $host) { echo "Host: $hostn"; echo "Status: " . $status[$id] . "nn"; } ?>
我们使用()来等待打开连接事件。 () 调用系统的(2)函数进行工作:前三个参数是你要使用的数组; 您可以读取、写入和获取异常(分别针对三个参数)。 () 你可以通过设置$(秒)参数来等待事件的发生——当事件发生时,相应的数据就会被写入到你传入的参数中。
以下是PHP 4.1.0之后版本的实现。 如果你在编译PHP时已经包含了(ext/)支持,那么可以使用与上面类似的代码,但是需要使用ext/函数来实现上面/函数的功能。 主要区别在于,我们使用以下函数来建立连接,而不是 ():
代码如下所示:
<?php // This value is correct for Linux, other systems have other values 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 || socket_last_error() == EINPROGRESS) { $errno = EINPROGRESS; return $s; } } $errno = socket_last_error($s); $errstr = socket_strerror($errno); socket_close($s); return false; } ?>
现在将()替换为(),将fread()替换为(),将()替换为(),将()替换为(),就可以执行脚本了!
PHP5 的高级之处在于,你可以使用 () 来处理几乎所有事情——例如,你可以使用它通过 STDIN 接收键盘输入并将其保存到数组中,还可以从通过 () 打开的管道接收数据。