我在浏览器中,点击一个按钮a,启动了一个定时器A,我又点击了相同的按钮a,又启动了一个定时器B(定时器A和定时器B是实现相同的功能的),如何实现:点击一个按钮,只能启动一个定时器A,再次点击这个按钮后,无法新建定时器B?代码如下:
public function onConnect($connection)
{
// 定义并执行一个定时器
$time_interval = 5;// 每5秒执行一次定时器
// 给connection对象临时添加一个timer_id属性保存定时器id
$connection->timer_id = Timer::add($time_interval, function () use ($connection) {
// 连接数据库并时时取出数据
$id = '1DF22E206ACE919DC47E1A840594CC72';
$infoMessage = Db::name('message')->find($id);
$data = $infoMessage['title'];
// 将数据库数据时时发送给客户端
$connection->send($data);
file_put_contents("wangjing.txt", "定时器ID:" . $connection->timer_id . ",时时数据:" . $data . ",当前时间:" . date("y-m-d H:i:s") . "\n", FILE_APPEND | LOCK_EX);
});
file_put_contents("wangjing.txt", "定时器ID为:$connection->timer_id\n", FILE_APPEND | LOCK_EX);//有多少个子进程,就会打印多少个定时器ID
}
用共享内存Apcu或者redis增加一个业务锁,定时器结束时销毁锁;
APCu是血缘关系进程可以共享,redis无限制甚至可以不是一台服务器实例,根据自身情况选择;
当点击按钮时,创建锁并创建定时器,如果创建锁失败了,则忽略;注意在定时器销毁时回收锁;
谢谢回答。但是你的方案需要利用其它的技术来实现,我想问:workerman本身能否避免重复创建定时器?
目前定时器没有实现,定时器id是自增的,你也可以通过利用workerman的eventloop自行实现定时器,使用静态数组保存timer的id,判断id是否存在