默认分类

PHP多线程模块pthreads的使用

最近开发一个项目,需要在一个周期内执行许多个类似的任务。

印象中的PHP无法异步执行代码,所以计划使用PHP格式化MySQL的数据,然后提交给Bash Shell Script处理,毕竟在Bash Shell下,可以利用许多GNU程序的组合来实现我的需求,更重要的是在命令末尾加一个”&”符号,即可把任务丢到后台执行,立刻开始下一个任务,最后一切就绪后再提交结果给PHP收尾。

不得不说这是一个很糟糕的方案,虽然数据经过PHP初步格式化,但Shell Script仍然要使用一部分文字处理工具处理数据,其中可能因为某个字段数据比较特殊而出错,由于执行任务需要调用多个程序,效率低下,部分程序之间要使用管道,这些都增加了大量的服务器CPU以及物理内存资源的消耗,更烦的是要循环查询是否所有线程都已经结束工作……

为了让任务能高效率完成,于是寻找了一下有关PHP多线程的解决方案,发现原来PHP有一个提供多线程功能的模块——pthreads。

PHP官方对pthreads模块的介绍:

pthreads is an Object Orientated API that allows user-land multi-threading in PHP. It includes all the tools you need to create multi-threaded applications. PHP applications can create, read, write, execute and synchronize with Threads, Workers and Threaded objects.

介绍说pthreads模块提供了所有构建多线程PHP应用程序所需的工具,果然是世界上最好的语言。

根据PHP官方的文档,使用pthreads模块,需要开启线程安全功能,也就是编译PHP的时候,必须加上参数–enable-maintainer-zts。

此外,开启pthreads模块后,无法使用CGI模式运行PHP。

从PECL可以取得pthreads源码,继而进行编译安装,如果安装了php pear,还可以通过pecl命令安装:

下面说说pthreads模块的使用。

这是pthreads模块提供的Thread类的概要:

可以看到Thread是继承了Threaded类,因此我们要使用多线程功能时,直接需要创建一个继承于Thread的类即可:

其中run()方法与start()方法是关键。

在需要创建线程执行任务时,调用的是start()方法,而start()又会调用run()方法。

例:

上面的代码,会另起一个线程,输出一个随机数字。

如果我要在十秒后才输出这个随机数字,而且要输出100次,传统来说,至少需要1000秒才能完成输出任务,但使用线程,可以让所有输出几乎同时在十秒完成。

例:

上面的代码,使用了数组,每个数组元素都是一个myclass类的对象,这些对象会同时(虽然创建对象,开始线程等操作也需要时间,但时间非常短,可以忽略)创建一百个线程,这一百个线程同时开始十秒的延迟,十秒后同时输出一个数字:

Pthreads

由于使用的是线程模式,创建一个PHP进程即可处理所有线程,现在无需额外格式化数据,使用PHP的函数实现了所需的功能,相比之前不仅多Bash进程,还多执行各种杂七杂八程序的方案,任务执行效率大大提高。