java通过处理程序消息以最小的分配传递数组副本?
我正在后台线程上读取蓝牙数据流,并将该数据通过Message Handler传递给UiThread进行处理和显示。有关该过程的更详细描述,请参见here
目前,我正在将InputStream读入一个byte[]
,并使用Handler.obtainMessage()获取一条以字节数组作为对象参数的消息
我遇到了一个problem,其中数据包相互覆盖,因为数组没有跨线程锁定,并且在UiThread处理它之前在后台被覆盖。显而易见的解决方案是将数组复制到一个新数组,并传递该新对象
问题是,这在Android上非常昂贵,我将获得相当连续的数据流。有没有更好的方法将这些数据传递给主UiThread? 也许是通过同步字节数组,还是通过一种更节省内存的方式复制数组
# 1 楼答案
我不知道安卓系统,但通常会将这些数据读入动态分配的缓冲区,在消息中发布其引用,然后立即分配一个新的,为下一批数据做好准备。这消除了复制,并确保两个线程始终在不同的数据上运行
Rgds, 马丁
# 2 楼答案
在安卓系统中实现这一点的典型方式是拥有一个分配对象池。上这门课:
您可以这样管理它们:
# 3 楼答案
这听起来像是你想要的字节数组池,你可以签出使用,并在完成后签入。一个实现可能看起来像
免责声明:我还没有真正测试或编译这段代码,它只是为了传达基本的想法
有了它,在任何给定的时间,您都有可能分配到最少数量的byte[]对象。理想情况下,如果出于某种原因,它扩展了一堆,而现在所需的池大小更小,您还需要添加一些代码来减少池大小
我个人认为,在你是否需要微优化之前,你可能过于担心微优化了。(或者你可能已经分析了你的应用程序,并且知道你需要它。)
更新:Hackbod的解决方案实际上比我建议的更有效,尽管它仍然可能会受到池中对象太多的影响
# 4 楼答案
数据进入与被消耗的速度有多快
为什么不分配第二个数组,一个用于读取,一个用于写入,根据需要切换
当流写入数组1后,释放其互斥量,等待数组2变为可用。然后可以通过处理程序将数组1传递给UI线程,该线程将获得该数组的锁。通过这样切换阵列,您可以确保数据不会丢失,因为对每个阵列的访问都是通过互斥控制的
然而,如果数据的输入速度比读取速度快,则可能会出现问题。(蓝牙数据蒸汽能承受得起封锁和等待吗?)