使用多线程的PHP OOP脚本意外终止

时间:2015-04-09 22:37:11

标签: php multithreading oop

嗨,我在尝试让线程正常运行时遇到问题。问题是我的php脚本会在执行期间意外终止于2个特定点中的1个,并在其余时间工作。

我创建了一个产生相同结果的测试场景:

此脚本创建5个线程。每个线程在每次迭代时将随机数从10到20加起来。

其次,Summary_Thread会在打印摘要之前检查所有线程的完成时间......这就存在问题。

脚本在Summary_Thread :: run和Stack_Item_Container_Stack :: Compile_Summary期间终止,在Summary_Thread :: run结束时间接调用。

#!/usr/bin/php
<?php

ini_set('max_execution_time', 0);
ini_set('display_errors', 1);
error_reporting(E_ALL ^ E_NOTICE);
ignore_user_abort();

class Summary_Thread_Container
{
    public $stack_item_container_stack;
    private $summary_thread;

    function __construct($thread_count, Stack_Item_Container_Stack $stack_item_container_stack)
    {
        $this->stack_item_container_stack = $stack_item_container_stack;

        $this->summary_thread = new Summary_Thread($thread_count, $this);
        $this->summary_thread->start();
    }

    public function Compile_Summary(){ $this->stack_item_container_stack->Compile_Summary(); }
}

class Summary_Thread extends Worker
{
    private $summary_thread_container;
    private $thread_count;

    function __construct($thread_count, Summary_Thread_Container $summary_thread_container)
    {
        $this->summary_thread_container = $summary_thread_container;
        $this->thread_count = $thread_count;
    }

    public function run()
    {
        $thread_count = 0;

        echo "\n**************************************  Stack Thread Count: {$this->thread_count} \n";

        echo "*** START.\n";

        if($this->thread_count == $thread_count)
            echo "*** THREAD COUNTS MATCH.\n";
        else
            echo "*** THREAD COUNTS DO NOT MATCH.\n";

        while($this->thread_count != $thread_count)
        {
            $temp_SIC = $this->summary_thread_container->stack_item_container_stack->first_stack_item_container;
            $thread_count = 0;

            while($temp_SIC)
            {
                $thread_count++;

                echo "**************************************  Thread Count: {$thread_count} \n";

                $temp_SIC = $temp_SIC->Get_Next_Stack_Item_Container();
            }

            echo "*** END.\n";

            if($this->thread_count == $thread_count)
                echo "*** THREAD COUNTS MATCH.\n";
            else
                echo "*** THREAD COUNTS DO NOT MATCH.\n";
        }

        $this->Compile_Summary();
    }

    public function Compile_Summary(){ $this->summary_thread_container->Compile_Summary(); }
}

class Stack_Item_Container_Stack
{
    public $first_stack_item_container;
    private $thread_count;
    private $summary_thread_container;

    function __construct()
    {
        $this->first_stack_item_container = null;
        $this->thread_count = 0;

        for($i = 0; $i < 5; $i++)
        {
            echo "       * Creating Stack Item Container: {$i}\n";

            $this->thread_count++;
            $this->Add_Stack_Item_Container(new Stack_Item_Container(rand(10, 20), $i, $this));
        }

        $this->summary_thread_container = new Summary_Thread_Container($this->thread_count, $this);
    }

    public function Add_Stack_Item_Container(Stack_Item_Container $stack_item_container)
    {
        echo "       * Adding Stack Item Container *\n";

        if($this->first_stack_item_container)
        {
            $temp_stack_item_container = $this->first_stack_item_container;

            while($temp_stack_item_container->Get_Next_Stack_Item_Container())
                $temp_stack_item_container = $temp_stack_item_container->Get_Next_Stack_Item_Container();

            $temp_stack_item_container->Set_Next_Stack_Item_Container($stack_item_container);
        }
        else $this->first_stack_item_container = $stack_item_container;
    }

    public function Compile_Summary()
    {
        echo "\n";
        echo "===============\n";
        echo "=== Summary ===\n";
        echo "===============\n";
        echo "\n";

        $temp_SIC = $this->first_stack_item_container;

        while($temp_SIC)
        {
            echo "    Thread ID {$temp_SIC->member_variables[0]} ({$temp_SIC->member_variables[4]}) has a Total of {$temp_SIC->member_variables[2]}";
            echo "\n";

            $temp_SIC = $temp_SIC->Get_Next_Stack_Item_Container();
        }

        echo "\n";

        $this->Kill();
    }

    private function Kill()
    {
        while($this->first_stack_item_container)
        {
            $temp_SIC = $this->first_stack_item_container;

            $this->first_stack_item_container = $this->first_stack_item_container->Get_Next_Stack_Item_Container();

            $temp_SIC->Kill();
        }

        unset($this->summary_thread_container);
        unset($this);
    }
}

class Stack_Item_Container
{
    private $stack_item_container_stack;
    private $next_stack_item_container;

    public $member_variables;

    public $stack_item_thread;

    function __construct($time, $index, Stack_Item_Container_Stack $stack_item_container_stack)
    {
        $this->stack_item_container_stack = $stack_item_container_stack;
        $this->next_stack_item_container = null;

        $this->member_variables = new Stackable();
        $this->member_variables[] = -1;
        $this->member_variables[] = $time;
        $this->member_variables[] = 0;
        $this->member_variables[] = false;
        $this->member_variables[] = $index;

        $this->stack_item_thread = new Stack_Item_Thread($this->member_variables, $this);
        $this->stack_item_thread->start();
    }

    public function Get_Stack_Item_Container_Stack(){ return $this->stack_item_container_stack; }

    public function Get_Next_Stack_Item_Container(){ return $this->next_stack_item_container; }
    public function Set_Next_Stack_Item_Container(Stack_Item_Container $next_SIC){ $this->next_stack_item_container = $next_SIC; }

    public function Kill()
    {
        $this->stack_item_thread->kill();
        unset($this->member_variables);
        unset($this);
    }
}

class Stack_Item_Thread extends Worker
{
    private $stack_item_container;
    private $member_variables;

    function __construct($member_variables, Stack_Item_Container $stack_item_container)
    {
        $this->member_variables = $member_variables;
        $this->stack_item_container = $stack_item_container;
    }

    public function run()
    {
        $this->member_variables[0] = $this->getThreadId();
        $total = 0;

        echo "\n";

        for($i = 0; $i < $this->member_variables[1]; $i++)
        {
            $total += $i;
            $val = $i + 1;

            echo "Thread ID ({$this->member_variables[4]}): {$this->member_variables[0]}:";
            echo " Count: {$val} of {$this->member_variables[1]}";
            echo "\n";
        }

        echo "\n";

        $this->member_variables[2] = $total;
        $this->member_variables[3] = true;
    }
}

$stack_item_container_stack = new Stack_Item_Container_Stack();

OUTPUT 1(当它工作时):

**************************************  Stack Thread Count: 5
*** START.
*** THREAD COUNTS DO NOT MATCH.
**************************************  Thread Count: 1
**************************************  Thread Count: 2
**************************************  Thread Count: 3
**************************************  Thread Count: 4
**************************************  Thread Count: 5
*** END.
*** THREAD COUNTS MATCH.

===============
=== Summary ===
===============

    Thread ID 139975400195840 (0) has a Total of 105
    Thread ID 139975389705984 (1) has a Total of 153
    Thread ID 139975378360064 (2) has a Total of 153
    Thread ID 139975367014144 (3) has a Total of 55
    Thread ID 139975130801920 (4) has a Total of 153

输出2 :(它将终止的第一点):

**************************************  Stack Thread Count: 5
*** START.
*** THREAD COUNTS DO NOT MATCH.

输出3 :(它将终止的第二点)

**************************************  Stack Thread Count: 5
*** START.
*** THREAD COUNTS DO NOT MATCH.
**************************************  Thread Count: 1
**************************************  Thread Count: 2
**************************************  Thread Count: 3
**************************************  Thread Count: 4
**************************************  Thread Count: 5
*** END.
*** THREAD COUNTS MATCH.

只是为了尽可能多地提供您的信息: (可能不相关,但以防万一)

对配置所做的更改:

文件:/etc/sysctl.conf,所做的更改:net.ipv4.tcp_fin_timeout = 10

文件:php.ini,Changes Made:extension = php_pthreads.dll

服务器:

Linux 2.6.32-504.8.1.el6.x86_64

PHP 5.5.13

Apache / 2.2.15(CentOS)

每个孩子的最大请求数:4000 - 保持活跃:关闭 - 最大连接数:100

超时连接:60 - 保持活跃:15

虚拟服务器否


请帮助:),问题会有所帮助......我什么都看不到?

提前致谢

1 个答案:

答案 0 :(得分:0)

我自己无法测试它,但是如果PHP在没有错误的情况下正常退出,那么它可能是由主线程退出之前任何其他线程完成的。尝试Thread :: join them(http://php.net/manual/en/thread.join.php),以便父线程等待它们完成。