疑问:

1、run 方法中的代码执行完毕之后,独立线程立即退出,并且等待合适的时机由创建者线程加入(join)。

只能创建者线程加入join吗,什么是join?

2、 Thread extends Threaded implements Countable , Traversable , ArrayAccess {}

Threaded是接口吗?接口怎么用?

3、$this->synchronized(function($thread){
            if (!$thread->done)
                $thread->wait();
        }, $this);什么意思?

4、Even if you kill() a thread, the isStarted() method will still return true.怎么回事?

5、join方法是不是和start对应?没有join,线程结束不了吗?执行当中的线程能不能加入join?

回答:

join起阻塞主线程(调用子线程的join方法的这个线程)的作用,防止子线程还未执行完毕时主线程就已经退出了的问题。

6、重要的是,Threaded 提供了隐式的线程安全机制,这个对象中的所有操作都是线程安全的。这句话怎么理解?

所有的操作都是线程安全的,什么是不安全的?

7、 Threaded implements Traversable , Countable , ArrayAccess {}这三个接口是什么东东?

8、Threaded   的  chunk方法不太理解,什么是对象属性表,怎么用这个东西?

 9、synchronized在发起调用的线程上下文中获取对象同步锁,然后同步执行代码块,什么意思?不太理解,最好找个例子。

 10、Worker 对象超出作用范围(没有指向它的引用了),怎么理解,线程对象还有指向它的引用?

11、这意味着程序员可以在程序执行过程中重用这个线程上下文: 在 Worker 对象的栈中添加对象会激活 Worker 对象执行被加入对象的 run 方法?这句话怎么理解,worker对象会执行添加到他的栈中对象的run方法,什么鬼?worker有栈?它的作用是什么?

 12、怎么是worker来执行已入栈的的对象,这里面是什么机制?

13、

Collectable extends Threaded {
/* 方法 */
public bool isGarbage ( void )
public void setGarbage ( void )

}

这是什么意思?不是说它是一个接口吗,怎么也可以使用extends,这不是一个类所用的吗?

 14、Collectable 的两个方法如何用? 

15、如何回收某个指定的线程对象?

16、public int Pool::submit ( Threaded $task )

将任务提交到 Pool 中的下一个 Worker 对象,这些worker是并发执行的吗?是如何调度这些worker的?

17、创建互斥量,还给互斥量加锁,有什么用?用在哪里呀?

18、Cond 类中的静态方法可以用来直接访问 Posix 的条件变量。

Mutex 类中包含一些直接访问 Posix 互斥量的静态方法

Posix是什么东西?cond用在哪里?

 

 通过php官网上的安装方法来安装pthread比较有效,网上好多方法是不完整,无效的。

摘要:

Threaded

1、public array Threaded::chunk ( integer $size , boolean $preserve )

获取给定数量的对象属性表,可以选择是否保留键名称。

用法:

参数

size:要获取的条目数量
preserve:保留成员原有的键名称,默认为 false       

返回值:数组对象,包含从对象属性表中返回的给定数量的条目。   

用法:

$safe = new Threaded();

$safe->chunk(5);

2、public integer Threaded::count ( void )

返回对象的属性数量

用法:

$safe = new Threaded();

count($safe)

3、public bool Threaded::extend ( string $class )

使一个类在运行时实现线程接口,从而变成线程类

 
应用:
<?php
class My {}
Threaded::extend(My::class);
$my = new My();
var_dump($my instanceof Threaded);
?>
结果:bool(true)
4、public boolean Threaded::merge ( mixed $from [, bool $overwrite ] )
from要合并的数据,overwrite:如果现有对象已经存在同键的数据,是否覆盖。默认为 true
用法:
$safe->merge($array);
$safe->merge($stdClass);
object(Threaded)#2 (13) {
  ["0"]=>
  int(0)
  ["1"]=>
  int(1)
  ["2"]=>
  int(2)
  ["3"]=>
  int(3)
  ["4"]=>
  int(4)
  ["5"]=>
  int(5)
  ["6"]=>
  int(6)
  ["7"]=>
  int(7)
  ["8"]=>
  int(8)
  ["9"]=>
  int(9)
  ["foo"]=>
  string(3) "foo"
  ["bar"]=>
  string(3) "bar"
  ["baz"]=>
  string(3) "baz"
}
5、public boolean Threaded::notify ( void )
向对象发送唤醒通知
用法:$thread->notify();
6、public boolean Threaded::pop ( void )
弹出对象属性表中的最后一项数据
返回对象属性表中最后一项数据
7、public void Threaded::run ( void )
如果需要在多线程环境下执行代码,必须实现本方法
无返回值。即使代码中 run 方法有返回值,也会被忽略
8、public boolean Threaded::shift ( void )
弹出对象属性表中第一项数据,返回对象属性表中的第一项数据
用法:$safe->shift()
9、public mixed Threaded::synchronized ( Closure $block [, mixed $... ] )
block:要执行的代码块
...:传送给代码块的不定长参数      
返回值:代码块的返回值
用法:
$this->synchronized(function($thread){
            if (!$thread->done)
                $thread->wait();
        }, $this);

10、public boolean Threaded::unlock ( void ) 

从调用上下文中解锁被引用的对象

$this->unlock()

 11、public boolean Threaded::wait ([ integer $timeout ] )

让发起调用的线程上下文进入等待状态,直到收到其他线程的唤醒通知

timeout可选参数,等待时间,以微秒计      

 

Thread 类

下面的模式是:公私属性  【静态】 返回值  所属类::方法名(参数)

1、public integer Thread::getCreatorId ( void )

返回创建当前线程的线程ID。

用法:创建一个线程对象,在类内部可以这样调用:$this->getCreatorId();

2、public static Thread Thread::getCurrentThread ( void )

获取当前执行线程的引用。

用法:public function run() {
        var_dump(Thread::getCurrentThread());
    }

3、public static integer Thread::getCurrentThreadId ( void )

返回当前执行线程的ID

用法:public function run() {
        printf("%s is Thread #%lu\n", __CLASS__, Thread::getCurrentThreadId());

    }

4、public integer Thread::getThreadId ( void )

返回引用线程的ID

用法:public function run() {
        printf("%s is Thread #%lu\n", __CLASS__, $this->getThreadId());
    }

5、public boolean Thread::isJoined ( void )

线程是否已经被加入(join)

用法:var_dump($my->isJoined());

6、public boolean Thread::isStarted ( void )

线程是否开始执行

用法:$worker->isStarted()

7、public boolean Thread::join ( void )

让当前执行上下文等待被引用线程执行完毕,返回布尔值,表示操作成功与否

用法:$my->join()

8、public boolean Thread::start ([ integer $options ] )

在独立线程中执行 run 方法

options

可选参数,用来控制线程继承。默认值为 PTHREADS_INHERIT_ALL  

返回值:布尔值,表示操作成功与否

用法:$my->start()

Worker 类

Worker extends Thread implements Traversable , Countable , ArrayAccess {}

1、Worker 是一个具有持久化上下文的线程对象,通常用来在多个线程中使用。

public int Worker::collect ([ Callable $collector ] )

翻译:

收集完成任务的引用

允许程序员人工收回引用的一种机制。返回值是worker栈中的剩余待收回的个数。

用法:

echo "There are currently {$worker->collect()} tasks on the stack to be collected\n";

2、public int Worker::getStacked ( void )

返回栈中剩余的任务数量

用法:$worker->getStacked()

3、public bool Worker::isShutdown ( void )

Worker 对象是否被关闭

用法:

$worker = new Worker();
$worker->start();
var_dump($worker->isShutdown());
$worker->shutdown();
var_dump($worker->isShutdown());

输出:

bool(false)
bool(true)
即使$worker中没任务只要没有shutdown,都是true
4、public boolean Worker::isWorking ( void )
  3中已废除:Worker 对象是否正在执行栈中对象
  用Worker::getStacked()代替
5、public bool Worker::shutdown ( void )
在执行完已入栈对象之后,关闭这个 Worker 对象
返回值:布尔值,表示这个 worker 是否被成功关闭。
6、public int Worker::stack ( Threaded &$work )
将要执行的任务入栈到 Worker 对象,返回入栈之后,Worker 对象栈的大小。
用法:$worker->stack($work)
7、public int Worker::unstack ( void )

把 Worker 栈顶的(最老的那个)任务从栈中移除。返回出栈之后,Worker 栈的大小。

Collectable 

代表了垃圾回收的对象,在v2版本中是一个类,在v3中是一个需要线程实现的接口。

1、public bool Collectable::isGarbage ( void )

确定一个对象是否被标记为垃圾

2、public void Collectable::setGarbage ( void )

标记一个对象为垃圾

方法修饰符(v3以删除)

标记为 protected 的方法在同一时间仅允许一个线程访问

标记为 private 的方法只能由创建该对象的线程调用

Pool 类

Pool 对象是多个 Worker 对象的容器,同时也是它们的控制器。

size:Pool 对象可容纳的 Worker 对象的最大数量
class:Worker 的类
ctor:构造新的 Worker 对象时所需的参数
workers:指向 Worker 对象的引用
work:指向提交到 Pool 对象中的 Threaded 对象的引用
last:最后使用的 Worker 对象在池中的位置偏移量

1、public int Pool::collect ([ Callable $collector ] )

对于视为垃圾的引用,使用给定的垃圾收集器进行收集

collector

垃圾收集器,它返回一个布尔值表示这个任务是否可以被进行垃圾收集。 仅在极少的情况下需要一个自定义的垃圾收集器。      

返回值

池中剩余的待收集的任务数量。   

2、public Pool Pool::__construct ( integer $size [, string $class [, array $ctor ]] )

size

此 Pool 对象可创建的 Worker 对象的最大数量

class

新创建的 Worker 对象的类。 如果不指定类,那么会使用默认的 Worker 类。

ctor

创建 Worker 对象时所用到的参数,以数组方式传入

返回值

新创建的 Pool 对象     

用法:
class MyWorker extends Worker {
    
    public function __construct(Something $something) {
        $this->something = $something;
    }
    
    public function run() {
        /** ... **/
    }
}

$pool = new Pool(8, \MyWorker::class, [new Something()]);

var_dump($pool);

3、public void Pool::resize ( integer $size )
改变 Pool 对象的可容纳 Worker 对象的数量

4、public void Pool::shutdown ( void )
停止此 Pool 中所有的 Worker 对象。此方法调用会进入阻塞状态, 直到所有已经提交到这个 Pool 中的任务都执行完毕。
我觉得是将所有提交到这个pool中的线程执行完毕后,停止所有的worker。

5、public int Pool::submit ( Threaded $task )
将任务提交到 Pool 中的下一个 Worker 对象

返回值

执行新加入对象的 Worker 对象 ID

6、public int Pool::submitTo ( int $worker , Threaded $task )

将对象提交到 Pool 中某个特定的 Worker 对象来执行。Worker 的下标从 0 开始, 由于 Pool 中的线程是懒加载机制, 所以 Worker 对象仅在 Pool 需要执行任务的时候才会真正被创建。

用法:

class Task extends Threaded {
    public function run() {
        var_dump(Thread::getCurrentThreadID());
    }
}

$pool = new Pool(2);

$pool->submit(new Task());

for ($i = 0; $i < 5; ++$i) {
    $pool->submitTo(0, new Task()); // 将所有的任务都入栈到下标为 0 的 Worker
}

$pool->submitTo(1, new Task()); // 由于第二个 Worker 尚未存在,所以不可以将任务入栈到第二个 Worker

$pool->shutdown();

输出:

int(4475011072)
int(4475011072)
int(4475011072)
int(4475011072)
int(4475011072)
int(4475011072)

Fatal error: Uncaught Exception: The selected worker (1) does not exist in %s:%d
所以用这个方法,需要,这个worker事先被创建。

7、Mutex 类(已经移除)

1、final public static long Mutex::create ([ boolean $lock ] )

为调用者创建一个互斥量,同时也可以通过 lock 参数设置是否在创建完成之后立即加锁此互斥量

如果设置 lock 参数为 true,表示创建互斥量之后,立即加锁,然后再将互斥量句柄返回给调用者

返回值:新创建的互斥量句柄,这个互斥量可能已经处于加锁状态,由 lock 参数控制

/** 不可以使用 new 关键字,因为互斥量不是 PHP 对象 **/
$mutex = Mutex::create();
/** 你已经持有了这个互斥量的物理地址 **/
var_dump($mutex);
/** 不要忘记销毁你创建的互斥量 **/
Mutex::destroy($mutex);


输出:
int(40096976)

2、final public static boolean Mutex::destroy ( long $mutex )
当不再使用某个已经创建的互斥量句柄之后,程序员需要显式的销毁它。
布尔值,表示操作是否成功
用法:同上

3、final public static boolean Mutex::lock ( long $mutex )

尝试为调用者给互斥量加锁。

尝试给已经被其他线程加锁的互斥量再次加锁会导致调用者线程进入阻塞状态。

用法:

/** 不可以使用 new 关键字,因为互斥量不是 PHP 对象 **/
$mutex = Mutex::create();
/** 现在可以在任何线程上下文中给这个互斥量加锁了
 **/
var_dump(Mutex::lock($mutex));
/** 销毁一个处于加锁状态的互斥量的操作是无效的 **/
var_dump(Mutex::unlock($mutex));
/** 永远不要忘记销毁你创建的互斥量 **/
Mutex::destroy($mutex);

4、final public static boolean Mutex::trylock ( long $mutex )
尝试给一个互斥量加锁,即使这个互斥量已经被其他线程锁定,也不会导致调用者线程进入阻塞状态。
返回值:布尔值,表示操作是否成功

5、final public static boolean Mutex::unlock ( long $mutex [, boolean $destroy ] )

尝试为互斥量解锁,也可以通过 destroy 参数控制是否在解锁之后同时销毁此互斥量。 只有持有互斥量锁的线程才可以对这个互斥量进行解锁操作。

destroy

此参数为 true 表示如果解锁成功,则同时销毁此互斥量。

Cond 类(已经移除)

1、final public static boolean Cond::broadcast ( long $condition )

向所有由于调用 Cond::wait() 函数而进入条件阻塞状态的线程发送广播。

condition:通过调用函数 Cond::create() 获得的条件变量句柄。
返回值:布尔值,表示操作是否成功。
2、final public static long Cond::create ( void )
创建一个条件变量。
返回值:指向条件变量的句柄。
用法:
/** 不可以使用 new 关键字,因为 Cond 不是 PHP 对象 **/
$cond = Cond::create();
/** 现在你可以在任意线程上下文中使用此条件变量 **/
var_dump($cond);
/** 永远不要忘记销毁你创建的条件变量 **/
Cond::destroy($cond);
会输出:
int(4540682)

3、final public static boolean Cond::destroy ( long $condition )

当不再需要所创建的条件变量时,程序员必须显式的销毁它。 当调用 Cond::destroy() 函数时,必须保证其他线程没有处于等待此条件变量的阻塞状态(通过调用函数 Cond::wait() 进入条件阻塞状态)。   

4、final public static boolean Cond::signal ( long $condition )

发送唤醒信号

用法:

Cond::signal($cond)

5、final public static boolean Cond::wait ( long $condition , long $mutex [, long $timeout ] )

进入条件变量等待状态。通过 timeout 参数可以设置等待超时时间。