php 模拟多线程

1、linux下的php多线程

下面所讲的东西是源自php的pcntl_fork函数.因为这个函数依赖操作系统fork的实现,所以本文所讲的东西只适用于linux/unix。那么先看看这个函数的用法吧.php手册上是这么说的:

1

2

3

4

5

6

7

8

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

通过pcntl_fork创建一个子进程,如果返回值是-1的话,那么说明子进程创建失败.创建成功的进程id会返回给父进程,0返回给子进程.不好理解吧,所以应该这样写:

1

2

3

4

5

6

7

8

9

<?php

$pid = pcntl_fork();if($pid == -1){         //创建失败咱就退出呗,没啥好说的

         die('could not fork');

}else{        if($pid){                //从这里开始写的代码是父进程的,因为写的是系统程序,记得退出的时候给个返回值

                exit(0);

        }        else{                //从这里开始写的代码都是在新的进程里执行的,同样正常退出的话,最好也给一个返回值

                exit(0);

        }

}?>

这样一改好理解多了,如果你父进程希望知道子进程正常退出的话,可以加上前面的pcntl_wait。

2.通过stream_socket_client 方式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

function sendStream() {

    $english_format_number = number_format($number, 4, '.', '');

   

    echo $english_format_number

    exit();

    $timeout = 10;

    $result = array();

    $sockets = array();

    $convenient_read_block = 8192;

    $host = "test.local.com";

    $sql = "select waybill_id,order_id from xm_waybill where status>40 order by update_time desc limit 1 "

    $data = Yii::app()->db->createCommand($sql)->queryAll();

    $id = 0;

   

    foreach ($data as $k => $v) {

      if ($k % 2 == 0) {

        $send_data[$k]['body'] = NoticeOrder::getSendData($v['waybill_id']);

   

      } else {

        $send_data[$k]['body'] = array($v['order_id'] => array('extra' => 16)); 

      

      $data = json_encode($send_data[$k]['body']);

      $s = stream_socket_client($host . ":80", $errno, $errstr, $timeout, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);

      if ($s) { 

        $sockets[$id++] = $s;

        $http_message = "GET /php/test.php?data=" . $data . " HTTP/1.0\r\nHost:" . $host . "\r\n\r\n"

        fwrite($s, $http_message);

      } else

        echo "Stream " . $id . " failed to open correctly.";

      

    }

   

    while (count($sockets)) {

   

      $read = $sockets;

   

      stream_select($read, $w = null, $e = null, $timeout);

       if (count($read)) { 

        /* stream_select generally shuffles $read, so we need to

         compute from which socket(s) we're reading. */

        foreach ($read as $r) {

   

          $id = array_search($r, $sockets);

          $data = fread($r, $convenient_read_block);

          if (strlen($data) == 0) {

            echo "Stream " . $id . " closes at " . date('h:i:s') . ".<br>  ";

            fclose($r);

             unset($sockets[$id]);

          } else {

            $result[$id] = $data;

          }

        }

      } else

        /* A time-out means that *all* streams have failed

         to receive a response. */

        echo "Time-out!\n";

        break;

      

    

    print_r($result);

   

  }

3、通过多进程代替多线程

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

function daemon($func_name,$args,$number){

  while(true){

    $pid=pcntl_fork();

    if($pid==-1){

      echo "fork process fail";

      exit();

    }elseif($pid){//创建的子进程

   

      static $num=0;

      $num++;

      if($num>=$number){

        //当进程数量达到一定数量时候,就对子进程进行回收。

        pcntl_wait($status);

   

        $num--;

      

    }else{ //为0 则代表是子进程创建的,则直接进入工作状态

   

      if(function_exists($func_name)){

        while (true) {

          $ppid=posix_getpid();

          var_dump($ppid);

          call_user_func_array($func_name,$args);

          sleep(2);

        }

      }else{

        echo "function is not exists";

      }

      exit();  

    }

  }

function worker($args){ 

  //do something

  

daemon('worker',array(1),2);

 

来源:https://www.php.cn/php-weizijiaocheng-381235.html

posted @ 2019-10-16 15:21  陈俊武  阅读(495)  评论(0编辑  收藏  举报