由浅到深理解ROS(8)-线程管理

转自


单线程Spinning

ros::spin()是最简单的单线程自旋, 它会一直调用直到结束

用法:  ros::spin();

另一个单线程spinning是ros::spinOnce(),它定期调用等待在那个点上的所有回调

用法:  ros::spinOnce();

简单的我们自己实现一个用法相同的ros::spin()

这样:  ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));

ros::spinonce

这样:  ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));


以上,是它的基础用法,那么spin到底做了什么呢?

首先, 当我们调用ros::spin时, 会有一个互斥锁, 把你的回调队列加锁, 防止执行混乱. 

然后, 检测如果回调队列不为空, 则读取回调队列

最后,当while(nh.ok())为true时, 调用当前队列中的所有函数,如果有不满足的, 会重新放回队列中

 

所以listener中, 就一直执行这ros::spin来监听话题了.从这样看来,spin和spinOnce的区别之一,就是while(nh::ok())执行块的大小了. 另一个是等待时间, spin在执行时, 会指定一个返回前可以等待调用的时间. spin会等待0.1s而spinonce不会

spinOnce使得pub/sub为非阻塞锁 spin是客户端的, 因此是阻塞的.

这样就很好理解talker要用SpinOnce,有需要talk的时候发出,没有的时候不发送.而listener一直在阻塞着听


这样,再来说之前很流传的一句关于解释spin的话, "所有的回调函数都是spin调用的". 这是一句形象而不准确的话. 回调函数一直等待在回调队列中, 只要条件一满足就会发生回调, 而spin的作用, 只是创建了线程给这个回调函数去执行它, 这样多线程就不会影响其他的作业.

之所以用spin, 是因为rospy不愿指定线程模型, 在程序中将线程暴露出来, 而用spin来把它封装起来. 但你可以用多线程调用任意数量的回调函数.

没有用户订阅, 服务和回调是不会被调用的.


 

 

多线程Spinning

多线程Spinning

roscpp内部支持调用多线程, 有两个:

ros::MultiThreadedSpinner

ros::MultiThreadedSpinner是阻塞微调, 类似于ros::spin(), 你可以在它的构造函数中指定线程数量, 但如果不指定或者设为0, 它会根据你的CPU内核数创建线程.

1 ros::MultiThreadedSpinner spinner(4); // Use 4 threads
2 spinner.spin(); // spin() will not return until the node has been shutdown

ros::AsyncSpinner (since 0.10)

一个更有用的线程spinner是AsyncSpinner. 与阻塞的spin()不同, 它有start()和stop()调用, 并且在销毁时自动停止

1 ros::AsyncSpinner spinner(4); // Use 4 threads
2 spinner.start();
3 ros::waitForShutdown();

 

 

官方说明

Single-threaded Spinning

The simplest (and most common) version of single-threaded spinning is ros::spin()

切换行号显示
   1 ros::init(argc, argv, "my_node");
   2 ros::NodeHandle nh;
   3 ros::Subscriber sub = nh.subscribe(...);
   4 ...
   5 ros::spin();

In this application all user callbacks will be called from within the ros::spin() call. ros::spin() will not return until the node has been shutdown, either through a call to ros::shutdown() or a Ctrl-C

Another common pattern is to call ros::spinOnce() periodically: 

切换行号显示
   1 ros::Rate r(10); // 10 hz
   2 while (should_continue)
   3 {
   4   ... do some work, publish some messages, etc. ...
   5   ros::spinOnce();
   6   r.sleep();
   7 }

ros::spinOnce() will call all the callbacks waiting to be called at that point in time. 

Implementing a spin() of our own is quite simple: 

切换行号显示
   1 #include <ros/callback_queue.h>
   2 ros::NodeHandle n;
   3 while (ros::ok())
   4 {
   5   ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
   6 }

and spinOnce() is simply: 

切换行号显示
   1 #include <ros/callback_queue.h>
   2 
   3 ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0));

Note: spin() and spinOnce() are really meant forsingle-threaded applications(单线程的), and are not optimized for being called from multiple threads at once. See the multi-threaded spinning section for information on spinning from multiple threads. 

Multi-threaded Spinning

roscpp provides some built-in support for calling callbacks from multiple threads. There are two built-in options for this: 

ros::MultiThreadedSpinner

  • MultiThreadedSpinner is ablocking spinner(阻塞的), similar to ros::spin(). You can specify a number of threads in its constructor, but if unspecified (or set to 0), it will use a thread for each CPU core. 

    切换行号显示
       1 ros::MultiThreadedSpinner spinner(4); // Use 4 threads
       2 spinner.spin(); // spin() will not return until the node has been shutdown
       3 
    

ros::AsyncSpinner (since 0.10)

  • AsyncSpinner API (Jade)

  • A more useful threaded spinner is the AsyncSpinner(异步的). Instead of a blocking spin() call, it has start() and stop()calls, and will automatically stop when it is destroyed. An equivalent use of AsyncSpinner to the MultiThreadedSpinner example above, is: 

    切换行号显示
       1 ros::AsyncSpinner spinner(4); // Use 4 threads
       2 spinner.start();
       3 ros::waitForShutdown();


  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值