由浅到深理解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 shutdownros::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 hz2 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 threads2 spinner.spin(); // spin() will not return until the node has been shutdown3
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 threads2 spinner.start();3 ros::waitForShutdown();
總結
以上是生活随笔為你收集整理的由浅到深理解ROS(8)-线程管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步步编写操作系统 54 CPL和DPL
- 下一篇: 了解Entity Framework中事