PHP でマルチスレッドを実現する
マルチスレッドはプログラム実行の一形態であり、単一のプロセスが複数のスレッドを作成し、それらが同時に実行されます。このチュートリアルでは、PHP でのマルチスレッドについて説明し、それを実現する方法を示します。
PHP で並列同時実行拡張モジュール Parallel
を使用してマルチスレッドを実現する
Parallel
並列同時実行拡張機能を使用すると、PHP でマルチスレッドを実現できます。
拡張機能は、インタプリタスレッド parallel\Runtime
を提供します。parallel\Runtime
クラスからオブジェクトを作成して、スレッドを作成できます。
このクラスは、タスクを並列実行するようにスケジュールするメソッド run()
を提供します。パラメータとして Closure
を run
メソッドに渡すことができます。
このパラメーターは一般にタスク
と呼ばれ、メソッドの 2 番目のパラメーターとして配列を指定することもできます。配列の内容がタスクに渡されます。
Parallel
並列同時実行拡張機能をダウンロードする前に、いくつかの要件があります。PHP のバージョンは 8.0 で、Zend Thread Safe(ZTS)が有効になっている必要があります。
<pthread.h>
ヘッダーは別の要件です。次のように、pecl
から拡張機能をダウンロードできます。
pecl install parallel
for
ループを使用して、プログラムの並列実行をテストできます。
たとえば、run()
メソッドの内側でループを実行し、メソッドの外側で別のループを実行できます。このような状況では、コードの実行は並行して行われます。
たとえば、parallel\Runtime
クラスのオブジェクト $rt
を作成してから、そのオブジェクトを使用して run()
メソッドを呼び出します。run()
メソッド内に無名関数を記述します。
まず、for
ループを記述して、関数内に+
記号を 50 回出力します。次に、run()
メソッドの外で、別の for
ループを記述して、-
記号を 50 回出力します。
run()
メソッド内のループは別のスレッドで実行されるため、run()
メソッド外のループは同時に実行されます。その結果、以下の出力セクションに示すように、-
と+
の記号が同時に出力されます。
したがって、並列同時実行拡張機能を使用して、PHP でマルチスレッド化を実現できます。
サンプルコード:
$rt = new \parallel\Runtime();
$rt->run(function(){
for ($i = 0; $i < 50; $i++)
echo "+";
});
for ($i = 0; $i < 50; $i++) {
echo "-";
}
出力:
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
PHP で popen()
関数を使用してマルチスレッドを実現する
popen()
関数を使用して、PHP で並列プロセスを開くことができます。
関数がプロセスをフォークし、その結果、並列処理が実現されます。プロセスによるリソースの共有はありません。
このようにして、PHP でマルチスレッドを実現できます。popen()
関数は、フォークされたプロセスへのパイプを作成します。
popen()
関数をループして、マルチスレッドを実現するためのいくつかのプロセスを作成できます。popen()
関数は、最初のパラメーターとして command
を取り、2 番目のパラメーターとして mode
を取ります。
モードは、r
または w
のいずれかです。
たとえば、5 回ループする for
ループを作成します。ループ内で、5 回以上ループする別の for
ループを作成します。
子ループ内に、popen()
関数を格納する配列 $process
を作成します。PHP ファイル message.php
と r
モードを最初と 2 番目のパラメーターとして設定します。
次に、別の子ループを作成し、pclose()
関数を使用して $process
を閉じます。
ここでは、5つのプロセスが最初の子ループで並行して実行されます。プロセスは、pclose()
関数を使用して 2 番目の子ループで終了します。
これは、PHP で popen()
関数を使用してマルチスレッドを実現する方法です。
サンプルコード:
for ($i=0; $i<5; $i++) {
for ($j=0; $j<5; $j++) {
$process[$j] = popen('message.php', 'r');
}
for ($j=0; $j<5; ++$j) {
pclose($process[$j]);
}
}