PHP अनुप्रयोगों में मल्टी थ्रेडिंग का उपयोग कोई कैसे कर सकता है


414

क्या PHP में एक बहु-थ्रेडेड मॉडल को लागू करने का एक वास्तविक तरीका है कि क्या वास्तव में, या सिर्फ इसका अनुकरण कर रहा है। कुछ समय पहले यह सुझाव दिया गया था कि आप ऑपरेटिंग सिस्टम को PHP के निष्पादन योग्य किसी अन्य उदाहरण को लोड करने और अन्य युगपत प्रक्रियाओं को संभालने के लिए बाध्य कर सकते हैं।

इसके साथ समस्या यह है कि जब PHP कोड ने PHP उदाहरण को निष्पादित करना समाप्त कर दिया, तो यह याद में रहता है क्योंकि PHP के भीतर से इसे मारने का कोई तरीका नहीं है। इसलिए यदि आप कई धागों का अनुकरण कर रहे हैं तो आप कल्पना कर सकते हैं कि क्या होने वाला है। इसलिए मैं अभी भी एक ऐसा रास्ता खोज रहा हूं, जिसमें मल्टी-थ्रेडिंग की जा सके या PHP के भीतर से प्रभावी ढंग से अनुकरण किया जा सके। कोई विचार?


1
मेरा प्रश्न और उत्तर यहां देखें: stackoverflow.com/questions/2101640/…
powtac


pthreads एक्सटेंशन का उपयोग कैसे करें: phplobby.com/php-multi-thread-on-windows-pthreads-configuration
Emrah Mehmedov

ब्याज की शायद: pthreads.org
गिब्बो

अब 2020 में, यह "समानांतर" php.net/manual/en/intro.parallel.php लगता है कि हम "pthreads" के बजाय क्या चाहते हैं: stackoverflow.com/a/56451969/470749
रयान

जवाबों:


431

मल्टी-थ्रेडिंग php में संभव है

हाँ आप pthreads के साथ PHP में मल्टी-थ्रेडिंग कर सकते हैं

से पीएचपी प्रलेखन :

pthreads एक ऑब्जेक्ट-ओरिएंटेड एपीआई है जो PHP में मल्टी-थ्रेडिंग के लिए आवश्यक सभी उपकरण प्रदान करता है। PHP एप्लिकेशन थ्रेड, वर्कर्स और थ्रेडेड ऑब्जेक्ट के साथ बना, पढ़, लिख, निष्पादित और सिंक्रनाइज़ कर सकते हैं।

चेतावनी : pthreads एक्सटेंशन का उपयोग वेब सर्वर वातावरण में नहीं किया जा सकता है। PHP में थ्रेडिंग केवल CLI- आधारित एप्लिकेशन तक ही रहनी चाहिए।

सरल परीक्षण

#!/usr/bin/php
<?php
class AsyncOperation extends Thread {

    public function __construct($arg) {
        $this->arg = $arg;
    }

    public function run() {
        if ($this->arg) {
            $sleep = mt_rand(1, 10);
            printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
            sleep($sleep);
            printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
        }
    }
}

// Create a array
$stack = array();

//Initiate Multiple Thread
foreach ( range("A", "D") as $i ) {
    $stack[] = new AsyncOperation($i);
}

// Start The Threads
foreach ( $stack as $t ) {
    $t->start();
}

?>

प्रथम रन

12:00:06pm:     A  -start -sleeps 5
12:00:06pm:     B  -start -sleeps 3
12:00:06pm:     C  -start -sleeps 10
12:00:06pm:     D  -start -sleeps 2
12:00:08pm:     D  -finish
12:00:09pm:     B  -finish
12:00:11pm:     A  -finish
12:00:16pm:     C  -finish

दूसरा रन

12:01:36pm:     A  -start -sleeps 6
12:01:36pm:     B  -start -sleeps 1
12:01:36pm:     C  -start -sleeps 2
12:01:36pm:     D  -start -sleeps 1
12:01:37pm:     B  -finish
12:01:37pm:     D  -finish
12:01:38pm:     C  -finish
12:01:42pm:     A  -finish

वास्तविक विश्व उदाहरण

error_reporting(E_ALL);
class AsyncWebRequest extends Thread {
    public $url;
    public $data;

    public function __construct($url) {
        $this->url = $url;
    }

    public function run() {
        if (($url = $this->url)) {
            /*
             * If a large amount of data is being requested, you might want to
             * fsockopen and read using usleep in between reads
             */
            $this->data = file_get_contents($url);
        } else
            printf("Thread #%lu was not provided a URL\n", $this->getThreadId());
    }
}

$t = microtime(true);
$g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", rand() * 10));
/* starting synchronization */
if ($g->start()) {
    printf("Request took %f seconds to start ", microtime(true) - $t);
    while ( $g->isRunning() ) {
        echo ".";
        usleep(100);
    }
    if ($g->join()) {
        printf(" and %f seconds to finish receiving %d bytes\n", microtime(true) - $t, strlen($g->data));
    } else
        printf(" and %f seconds to finish, request failed\n", microtime(true) - $t);
}

3
@ बाबा, मैं Xampp सर्वर पर pthreads कॉन्फ़िगर और स्थापित करने में सक्षम नहीं हूं। क्या उसके लिए आपके द्वारा मेरी मदद की जाएगी?
इरफान

4
यहाँ विंडोज़ बाइनरी डाउनलोड करें windows.php.net/downloads/pecl/releases/pthreads/0.0.45
बाबा

17
यह अच्छा है, मैंने सालों से PHP को नहीं छुआ है और अब इसमें मल्टीथ्रेडिंग क्षमताएं हैं!
क्रूजर

1
अच्छा और सरल! सिर्फ FYI करें, मैं Azure Cloud Win सर्वर पर एक ऐप तैनात कर रहा हूं और यदि केवल मूल 1 कोर कॉन्फ़िगरेशन का चयन किया जाता है तो मल्टी-थ्रेडिंग तब तक उपलब्ध नहीं होगी जब तक कि अधिक कोर नहीं जोड़े जाते।
मिलन

3
कृपया सावधान रहें: जो वाटकिंस, के लेखक ने विस्तार के नए समानांतर विस्तार के पक्ष में विकास को
रोक दिया

42

आप पोप का उपयोग क्यों नहीं करते ?

for ($i=0; $i<10; $i++) {
    // open ten processes
    for ($j=0; $j<10; $j++) {
        $pipe[$j] = popen('script2.php', 'w');
    }

    // wait for them to finish
    for ($j=0; $j<10; ++$j) {
        pclose($pipe[$j]);
    }
}

4
मैं उपरोक्त समाधान का उपयोग कर रहा हूं, और ठीक काम करता हूं, मुझे लगता है कि यह php का उपयोग करके समानांतर प्रक्रिया करने का सबसे आसान तरीका था।
गॉड फादर

7
जैसे @ e-info128 ने कहा, यह कार्यान्वयन प्रक्रिया की मांग करता है, जिसका अर्थ है कि यह एक अलग प्रक्रिया पर चल रहा है, और प्रक्रिया संसाधनों को साझा नहीं करता है। यह कहा जा रहा है, अगर हाथ में काम करने के लिए संसाधनों को साझा करने की आवश्यकता नहीं है, तो यह अभी भी काम करेगा और यह समानांतर में चलेगा।
रफी

1
सत्र चर का उपयोग किए बिना आप चरों को कैसे पास करेंगे?
एटवेलपब

@atwellpub कोई रास्ता नहीं, ये अलग-अलग प्रक्रियाएं हैं जो कोई संसाधन साझा नहीं करते हैं। यहां तक ​​कि सत्र भी अजीब आईपीसी तंत्र होंगे
चोलथी पॉल टिटोपिक

1
उन्हें डेटा पास करने के लिए, आप तर्कों और रेडिस सर्वर का भी उपयोग कर सकते हैं।
अमीर फ़ॉ

21

थ्रेडिंग स्टॉक PHP में उपलब्ध नहीं है, लेकिन अतुल्यकालिक कॉल के रूप में HTTP अनुरोधों का उपयोग करके समवर्ती प्रोग्रामिंग संभव है।

कर्ल के टाइमआउट सेटिंग के साथ 1 पर सेट करें और उन प्रक्रियाओं के लिए समान सत्र_ का उपयोग करके जिन्हें आप एक दूसरे के साथ जोड़ना चाहते हैं, आप नीचे सत्र चर के साथ संवाद कर सकते हैं जैसा कि मेरे उदाहरण में है। इस पद्धति से आप अपने ब्राउज़र को बंद कर सकते हैं और समवर्ती प्रक्रिया अभी भी सर्वर पर मौजूद है।

इस तरह सही सत्र आईडी सत्यापित करना न भूलें:

http: //localhost/test/verifysession.php? sessionid = [ सही आईडी]

startprocess.php

$request = "http://localhost/test/process1.php?sessionid=".$_REQUEST["PHPSESSID"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
echo $_REQUEST["PHPSESSID"];

process1.php

set_time_limit(0);

if ($_REQUEST["sessionid"])
   session_id($_REQUEST["sessionid"]);

function checkclose()
{
   global $_SESSION;
   if ($_SESSION["closesession"])
   {
       unset($_SESSION["closesession"]);
       die();
   }
}

while(!$close)
{
   session_start();
   $_SESSION["test"] = rand();
   checkclose();
   session_write_close();
   sleep(5);
}

verifysession.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
var_dump($_SESSION);

closeprocess.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
$_SESSION["closesession"] = true;
var_dump($_SESSION);

4
पिछली बार जब मैंने जाँच की थी (कुछ साल पहले) php ने फाइल आधारित सत्र भंडारण को एक साथ दो प्रक्रियाओं द्वारा एक्सेस करने की अनुमति नहीं दी थी। यह फ़ाइल को लॉक कर देता है और दूसरी प्रक्रिया को वहाँ बैठना पड़ता है ताकि पहली स्क्रिप्ट के रुकने का इंतज़ार किया जा सके। मैं वेबसर्वर पर्यावरण की बात कर रहा हूं, सीएलआई की नहीं।
अलेक्सई टेनित्सकी

5
set_time_limit(0);ओह! कभी नहीं, कभी ऐसा करो।
काफोसो

@ काफ़ोसो काफ़ोसो क्यों नहीं? वैसे मैं PHP के लिए एक वेब स्क्रिप्ट प्रोसेसर के रूप में सहमत हूं, लेकिन सीएलआई में क्यों नहीं? अगर कुछ गलत होता है, तो CLI को Ctrl + C ...
sijanec

14

जब आप थ्रेड नहीं कर सकते, तो आपके पास php में कुछ हद तक प्रक्रिया नियंत्रण है। दो फ़ंक्शन सेट जो यहां उपयोगी हैं, वे हैं:

प्रक्रिया नियंत्रण कार्य http://www.php.net/manual/en/ref.pcntl.php

POSIX फ़ंक्शंस http://www.php.net/manual/en/ref.posix.php

आप pcntl_fork के साथ अपनी प्रक्रिया को कांटा कर सकते हैं - बच्चे की पीआईडी ​​लौटा सकते हैं। तब आप उस PID का विरोध करने के लिए posix_kill का उपयोग कर सकते हैं।

उस ने कहा, यदि आप माता-पिता की प्रक्रिया को मारते हैं, तो एक संकेत को बच्चे की प्रक्रिया को भेज दिया जाना चाहिए ताकि वह मर जाए। अगर php खुद को पहचान नहीं रहा है, तो आप इसे प्रबंधित करने के लिए एक फ़ंक्शन रजिस्टर कर सकते हैं और pcntl_signal का उपयोग करके एक साफ निकास कर सकते हैं।


1
वह उत्तर अब बहुत पुराना है (जो यह जानकर बहुत ही उचित है कि यह 11 वर्ष पुराना है)। नीचे pthreads देखें।
मकिज पापरोकी

@MaciejPaprocki pThread अब 7.4 fromphp बंद है बजाय समानांतर का उपयोग
हवादार


10

मुझे पता है कि यह एक पुराना सवाल है, लेकिन खोज करने वाले लोगों के लिए, C में लिखा एक PECL एक्सटेंशन है जो PHP को अब मल्टी-थ्रेडिंग क्षमता देता है, यह यहाँ स्थित है https://github.com/krakjoe/pthreads


PThread को अब php 7.4 से बंद कर दिया गया है बजाय इसके समानांतर उपयोग करें
Airy

5

आप कमांड लाइन स्क्रिप्ट (जैसे कमांड लाइन php) को चलाने के लिए निष्पादन () का उपयोग कर सकते हैं, और यदि आप आउटपुट को किसी फाइल में पाइप करते हैं तो आपकी स्क्रिप्ट कमांड के खत्म होने का इंतजार नहीं करेगी।

मुझे php CLI वाक्यविन्यास याद नहीं है, लेकिन आप कुछ ऐसा चाहते हैं:

exec("/path/to/php -f '/path/to/file.php' | '/path/to/output.txt'");

मुझे लगता है कि सुरक्षा कारणों से कुछ साझा होस्टिंग सर्वरों ने डिफ़ॉल्ट रूप से निष्पादन () को अक्षम कर दिया है, लेकिन एक कोशिश के लायक हो सकता है।


4

आप थ्रेडिंग का अनुकरण कर सकते हैं। PHP पॉपेन (या proc_open) के माध्यम से पृष्ठभूमि प्रक्रियाएं चला सकती है। उन प्रक्रियाओं को स्टडिन और स्टडआउट के माध्यम से संप्रेषित किया जा सकता है। बेशक वे प्रक्रियाएं खुद एक php प्रोग्राम हो सकती हैं। वह शायद उतना ही करीब होगा जितना आपको मिलेगा।


3

आप जो करने की कोशिश कर रहे हैं उसके आधार पर आप इसे प्राप्त करने के लिए curl_multi का उपयोग भी कर सकते हैं।


3

मुझे पता है कि यह पुराना है, लेकिन आप http://phpthreadlib.sourceforge.net/ पर देख सकते हैं

यह द्वि-दिशात्मक अंतर-थ्रेड संचार का समर्थन करता है और इसमें बच्चे के थ्रेड्स (अनाथों को रोकने) को मारने के लिए बिलिन प्रोटेक्शन भी हैं।


3

आप का विकल्प हो सकता है:

  1. multi_curl
  2. एक ही के लिए सिस्टम कमांड का उपयोग कर सकते हैं
  3. आदर्श परिदृश्य है, C भाषा में थ्रेडिंग फ़ंक्शन बनाएं और PHP में संकलन / कॉन्फ़िगर करें। अब वह फंक्शन PHP का फंक्शन होगा।


3

Pcntl_fork के बारे में कैसे?

उदाहरण के लिए हमारे मैनुअल पेज की जाँच करें: PHP pcntl_fork

<?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
    }

?>

2

pcntl_forkयदि यह सुरक्षित मोड चालू है, तो वेब सर्वर वातावरण में काम नहीं करेगा । इस स्थिति में, यह केवल PHP के CLI संस्करण में काम करेगा।


1

यदि आप एक लिनक्स सर्वर का उपयोग कर रहे हैं, तो आप उपयोग कर सकते हैं

exec("nohup $php_path path/script.php > /dev/null 2>/dev/null &")

यदि आप की जरूरत है कुछ args पास

exec("nohup $php_path path/script.php $args > /dev/null 2>/dev/null &")

स्क्रिप्ट में

$args = $argv[1];

या सिम्फनी https://symfony.com/doc/current/compords/process.html का उपयोग करें

$process = Process::fromShellCommandline("php ".base_path('script.php'));
$process->setTimeout(0);     
$process->disableOutput();     
$process->start();

-1

मेरी वर्तमान टिप्पणी के लेखन के रूप में, मैं PHP थ्रेड्स के बारे में नहीं जानता। मैं स्वयं यहाँ उत्तर की तलाश में आया था, लेकिन एक समस्या यह है कि PHP प्रोग्राम जो वेब सर्वर से अनुरोध प्राप्त करता है, एक कंसोल एप्लिकेशन को पूरे उत्तर फॉर्मूलेशन को दर्शाता है, जो इसके आउटपुट, अनुरोध के उत्तर, को बाइनरी फ़ाइल में संग्रहीत करता है। कंसोल प्रोग्राम लॉन्च करने वाला PHP प्रोग्राम बाइनरी फ़ाइल बाइट-बाइट प्राप्त करता है जो प्राप्त अनुरोध के उत्तर के रूप में है। कंसोल एप्लिकेशन को सर्वर पर चलने वाली किसी भी प्रोग्रामिंग भाषा में लिखा जा सकता है, जिसमें उचित थ्रेडिंग समर्थन भी शामिल है, जिसमें ओपन सीएमपी सहित सी ++ प्रोग्राम शामिल हैं।

एक अविश्वसनीय, गंदे, चाल के लिए एक कंसोल एप्लिकेशन को निष्पादित करने के लिए PHP का उपयोग करना है, "नाम",

uname -a

और सर्वर सॉफ्टवेयर के सटीक संस्करण का पता लगाने के लिए HTML आउटपुट में उस कंसोल कमांड के आउटपुट को प्रिंट करें। फिर सॉफ़्टवेयर के सटीक समान संस्करण को वर्चुअलबॉक्स उदाहरण में स्थापित करें, जो कुछ भी पूरी तरह से स्व-निहित, अधिमानतः स्थिर, बायनेरिज़ को संकलित / इकट्ठा करें जो एक चाहता है और फिर उन्हें सर्वर पर अपलोड करें। उसके बाद से PHP एप्लिकेशन कंसोल बिन अनुप्रयोग की भूमिका में उन बायनेरिज़ का उपयोग कर सकता है जिसमें उचित मल्टी-थ्रेडिंग है। यह एक स्थिति के लिए एक गंदा, अविश्वसनीय, वर्कअराउंड है, जब सर्वर प्रशासक ने सभी आवश्यक प्रोग्रामिंग भाषा कार्यान्वयन को सर्वर पर स्थापित नहीं किया है। देखने की बात यह है कि हर अनुरोध पर कि PHP एप्लिकेशन को कंसोल एप्लिकेशन (एस) को समाप्त करता है / बाहर निकलता है / get_killed प्राप्त करता है।

होस्टिंग सेवा प्रशासक इस तरह के सर्वर उपयोग पैटर्न के बारे में क्या सोचते हैं, मुझे लगता है कि यह संस्कृति के लिए वरदान है। उत्तरी यूरोप में सेवा प्रदाता को क्या अधिकार प्राप्त है और यदि कंसोल आदेशों के निष्पादन की अनुमति दी गई थी और गैर-मैलवेयर फ़ाइलों को अपलोड करने की अनुमति दी गई थी और सेवा प्रदाता को कुछ मिनटों के बाद या 30 सेकंड के बाद किसी भी सर्वर प्रक्रिया को मारने का अधिकार है , तो होस्टिंग सेवा प्रशासकों के पास एक उचित शिकायत बनाने के लिए कोई तर्क नहीं है। संयुक्त राज्य अमेरिका और पश्चिमी यूरोप में स्थिति / संस्कृति बहुत अलग है और मेरा मानना ​​है कि अमेरिका और / या पश्चिमी यूरोप में एक बहुत अच्छा मौका है कि होस्टिंग सेवा प्रदाता उपरोक्त वर्णित ट्रिक का उपयोग करने वाले होस्टिंग ग्राहकों की सेवा करने से इनकार कर देगा। यह सिर्फ मेरा अनुमान है, यूएस के साथ मेरे व्यक्तिगत अनुभव को देखते हुए होस्टिंग सेवाओं और पश्चिमी यूरोपीय होस्टिंग सेवाओं के बारे में दूसरों से जो मैंने सुना है उसे देखते हुए। मेरी वर्तमान टिप्पणी (2018_09_01) के लेखन के रूप में मैं दक्षिणी-यूरोपीय होस्टिंग सेवा प्रदाताओं, दक्षिणी-यूरोपीय नेटवर्क प्रशासकों के सांस्कृतिक मानदंडों के बारे में कुछ नहीं जानता।


-3

हो सकता है कि मुझे कुछ याद आया हो, लेकिन निष्पादन ने विंडोज़ वातावरण में मेरे लिए अतुल्यकालिक के रूप में काम नहीं किया, जिसका मैंने विंडोज़ में अनुसरण किया और यह आकर्षण की तरह काम करता है।

$script_exec = "c:/php/php.exe c:/path/my_ascyn_script.php";

pclose(popen("start /B ". $script_exec, "r"));

1
PHP में मल्टीथ्रेडिंग हैक करने के लिए आपको कई पोपेन () स्टेटमेंट खोलने चाहिए (PHP इसे पूरा होने का इंतजार नहीं करेगा)। फिर आधा दर्जन या उसके बाद आप खुले हैं उन पर pclose () कॉल करें (PHP pclose पर इंतजार करेंगे () पूरा करने के लिए)। आपके कोड में आप प्रत्येक थ्रेड को खोलने के तुरंत बाद बंद कर देते हैं ताकि आपका कोड मल्टीथ्रेडेड की तरह व्यवहार न करे।
कैमिक्नर

-5

मल्टीथ्रेडिंग का अर्थ है एक साथ कई कार्यों या प्रक्रियाओं का प्रदर्शन करना, हम इसे निम्नलिखित कोड का उपयोग करके php में प्राप्त कर सकते हैं, हालाँकि php में मल्टीथ्रेडिंग को प्राप्त करने का कोई सीधा तरीका नहीं है लेकिन हम निम्न तरीके से लगभग समान परिणाम प्राप्त कर सकते हैं।

chdir(dirname(__FILE__));  //if you want to run this file as cron job
 for ($i = 0; $i < 2; $i += 1){
 exec("php test_1.php $i > test.txt &");
 //this will execute test_1.php and will leave this process executing in the background and will go         

 //to next iteration of the loop immediately without waiting the completion of the script in the   

 //test_1.php , $i  is passed as argument .

}

Test_1.php

$conn=mysql_connect($host,$user,$pass);
$db=mysql_select_db($db);
$i = $argv[1];  //this is the argument passed from index.php file
for($j = 0;$j<5000; $j ++)
{
mysql_query("insert  into  test   set

                id='$i',

                comment='test',

                datetime=NOW() ");

}

यह test_1.php को एक साथ दो बार निष्पादित करेगा और दोनों प्रक्रिया एक साथ पृष्ठभूमि में चलेगी, इसलिए इस तरह आप php में मल्टीथ्रेडिंग प्राप्त कर सकते हैं।

यह आदमी वास्तव में अच्छा काम किया php में Multithreading


इसके अलावा, इसमें मल्टीट्रेडिंग के साथ कुछ भी नहीं है। यह समानांतर प्रसंस्करण है। पूरी तरह से अलग चीजें।
डिजिटल मानव

एक इमरजेंसी, इमरजेंसी हैक के रूप में मेरी राय में, प्रस्तावित समाधान के पीछे का विचार बहुत उपयुक्त है, लेकिन मुझे लगता है कि अलग-अलग लोगों में "सच्चे मल्टी-थ्रेडिंग" का गठन करने के बारे में ज्वाला युद्ध हो सकता है, क्योंकि कंसीडर और हार्डवेयर के बीच एक अंतर है समानांतर प्रसंस्करण, जैसा कि वर्णित है: youtube.com/watch?v=cN_DpYBzKso
मार्टिन वाही
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.