PHP pThreads - 如何执行垃圾收集?

标签 php multithreading memory-leaks garbage-collection pthreads

给定以下代码,您如何确保已完成的 MyWorker 对象被销毁/释放它们的内存?

由于我的脚本需要大约 50 个线程不断地从 cURL 获取数据并进行处理。

我已经尝试过让线程永远不会离开 run(),或者如示例代码所示,它们离开运行并让收集函数生成它们的新副本。

但不管我在一分钟左右后达到内存限制是什么。你能告诉我我做错了什么吗?

class MyWorker extends Threaded
{
    public $complete;
    public function __construct() {$this->complete = false;}
    public function run() {$this->complete = true;}
}

$pool = new Pool(50);
for($i=0; $i<50; $i++)
    $pool->submit(new MyWorker());
$pool->collect(function($worker)
{
    global $pool;
    if($worker->complete == true)
        $pool->submit(new MyWorker());
    return $worker->complete;
});
$pool->shutdown();

最佳答案

为什么

我为什么要收集?

pthreads 提供的Worker 线程要求程序员保留对正在执行的Threaded 对象的正确引用。这对于程序员来说很难在用户空间可靠地实现,因此 pthreads 提供了 WorkersPool 抽象,它为您维护引用。

为了维护那些引用 pthreads 需要知道对象何时是垃圾,它为此提供了 Pool::collect 接口(interface)。 Pool::collect 采用一个闭包,该闭包应该接受一个 Threaded 对象并在传递的对象执行完毕时返回 bool 值 true

如何

手头的任务......

为了继续提交任务执行而不耗尽资源,您必须创建一个已完成任务的队列以重新提交到Pool

下面的代码展示了一种明智的做法:

<?php

define("LOG", Mutex::create());
/* thread safe log to stdout */
function slog($message, $args = []) {
    $args = func_get_args();
    if (($message = array_shift($args))) {
        Mutex::lock(LOG);
        echo vsprintf(
            "{$message}\n", $args);
        Mutex::unlock(LOG);
    }
}

class Request extends Threaded {
    public function __construct($url) {
        $this->url = $url;
    }

    public function run() {
        $response = @file_get_contents($this->url);

        slog("%s returned %d bytes",
            $this->url, strlen($response));

        $this->reQueue();
    }

    public function getURL()        { return $this->url; }

    public function isQueued()      { return $this->queued; }
    public function reQueue()       { $this->queued = true; }

    protected $url;
    protected $queued = false;
}

/* create a pool of 50 threads */
$pool = new Pool(50);

/* submit 50 requests for execution */
while (@$i++<50) {
    $pool->submit(new Request(sprintf(
        "http://google.com/?q=%s", md5($i))));
}

do {
    $queue = array();

    $pool->collect(function($request) use ($pool, &$queue) {
        /* check for items to requeue */
        if ($request->isQueued()) {
            /* get the url for the request, insert into queue */
            $queue[] = 
                $request->getURL();
            /* allow this job to be collected */
            return true;
        }
    });

    /* resubmit completed tasks to pool */
    if (count($queue)) {
        foreach ($queue as $queued)
            $pool->submit(new Request($queued));
    }

    /* sleep for a couple of seconds here ... because, be nice ! */
    usleep(2.5 * 1000000);
} while (true);
?>

关于PHP pThreads - 如何执行垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23341262/

相关文章:

c - 如何重新分配一些使用 calloc 分配的内存?

php - 如何在php中格式化纯文本?

c++ - 我想将我的计算内容放在辅助线程中,同时将主循环保留在主线程中

c# - 如何在 Web 应用程序上运行后台服务 - DotNetNuke

使用 RenderThread 和 UpdateThread 进行游戏的 Java LinkedList 迭代器和线程安全

memory-leaks - AudioToolbox 库 AVAudioPlayer 中的内存泄漏

java - Android - 静态上下文

带有 HAVING 和 MAX 的 php mysql 查询

php - 忘记密码成功连接到邮箱

php - 使用 json 传递输入字段类型和值