Guz*_*zba 3 java multithreading android
我很好奇这个方法的安全性,我考虑过在我的Android应用程序中传递触摸事件(并测试我对Java中的并发性的理解).这是基础知识:
我有一个SurfaceView连接到SurfaceHolder.Callback来获取用户输入事件,主要是onTouchEvent回调.在onTouchEvent调用该方法之后,我会看到是否event.getAction() == MotionEvent.ACTION_UP,如果是,则调用我已命名的postTouchEvent方法,该方法是我的应用程序线程的成员方法,用于更新应用程序的状态并绘制到画布.
SurfaceView
@Override
public boolean onTouchEvent(final MotionEvent event)
{
mAppThread.postTouchEvent(event);
}
Run Code Online (Sandbox Code Playgroud)
AppThread
private volatile MotionEvent mInputEvent;
public void postTouchEvent(final MotionEvent event)
{
this.mInputEvent = event;
}
@Override
public void run()
{
// while loop ...
if (this.mInputEvent != null)
{
final MotionEvent inputEvent = this.mInputEvent;
this.mInputEvent == null;
// update state based on inputEvent (not this.mInputEvent)
}
// draw to canvas
}
Run Code Online (Sandbox Code Playgroud)
现在我明白它肯定不是原子的,但是因为我从框架中接收它后将其视为不可变的,这不会起作用吗?(而不是同步post方法和if语句,我没有问题,但我要学习.)
这是我的想法.我知道我将对该对象有一个有效的引用,但我不确定我将实际看到该对象的状态.虽然测试一切都运行得很好,但我知道异常的线程异常是多么罕见,即使某些东西被破坏了.
此外,我可以看到一个问题:如果另一个MotionEvent出现,那么run()方法中的inputEvent可能会设置为与this.mInputEvent != null检查时引用的事件不同的事件,但这确实不是问题.
那么,有什么我遗失的,或者,就我的目的而言,这应该没问题吗?
ada*_*amp 16
不,这不安全,但不是因为你可能期望的原因.
ViewRoot.java,第1841行.这是在视图层次结构中调度MotionEvent的代码.第1841行是finally调用recycle()刚刚调度的MotionEvent 的块的一部分.
MotionEvents不像大多数对象那样被垃圾收集,它们被合并和回收,以避免在事件发送期间不必要的内存分配和垃圾收集.回收MotionEvent会将其返回到对象池,以便稍后在需要新的MotionEvent时再次使用.在recycle()调用之后,应将MotionEvent视为无效.
您的示例代码可能最终会读取已被框架重用的MotionEvent对象,现在包含完全不同的数据.
如果您计划在onTouchEvent返回后挂起到MotionEvent ,请使用它来克隆它MotionEvent.obtain(event).静态obtain()方法将从具有相同内容的对象池返回新的MotionEvent.
recycle()完成obtain()自己编写的MotionEvent后,应该调用它以将其返回到池中.如果你忘记了这一步,这将不是一个大问题,它将成为常规Java垃圾,框架将在需要时创建新的MotionEvent.但是,系统可以非常快速地调度MotionEvents,使得与此优化协作可以在某些设备上产生非凡的性能差异.