因此,IO不会阻止我的Android应用程序中的UI线程,我正在尝试将文件写入操作移动到单独的线程中。这是我用来启动低优先级线程从代码缓冲区写入1Mb的代码:
Thread t = new Thread(new Runnable()
{
@Override
public void run()
{
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
try
{
FileOutputStream fos = new FileOutputStream(filename));
try
{
final java.nio.channels.FileChannel outChannel = fos.getChannel();
outChannel.write(byteBuffer);
fos.getFD().sync();
}
finally
{
if (fos != null)
fos.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
t.setPriority(Thread.MIN_PRIORITY);
t.start();
当某些UI事件发生时,这些线程在我的应用程序中启动。不幸的是,我有时会注意到大量的滞后。我的UI将每10个左右冻结约2秒钟,我开始/完成上述线程之一。如果我注释掉线程代码,这些延迟就会消失。
如何阻止此IO操作阻止我的UI线程?
我不知道现在要做什么来诊断问题。我的理解是,当“outChannel.write”发生时,IO线程将被阻塞,因为它正在等待IO操作完成,这意味着我的UI线程将立即接管。是不是写操作实际上需要很大的CPU功率呢?
编辑:
使用StrictView(我很确定,因为它在我首先修复的UI线程中发现了一些无关的IO问题),我可以确认我的IO线程中没有IO。
运行traceview的结果非常令人费解。 UI问题是,当我执行拖放操作时,每10次左右我执行此操作,设备似乎冻结约0.5到1秒。你拖动的东西会冻结,延迟后最终会跳到你手指的位置。在traceview中,我一直拖拉,直到发生这种情况。对于在traceview中发生这种情况的情况,我的后台线程没有运行,但是突然阻塞大约1秒,我的UI线程上通常快速调用的操作大约需要花费x10来执行。例如,对.drawBitmap(具有固定大小的位图)的调用显示为每次执行~0.2s时执行相同的.drawBitamp调用占用此时间的十分之一。我可能只是读错了,但我不知道从这里去哪里或寻找什么。
答案 0 :(得分:6)
如何阻止此IO操作阻止我的UI线程?
I / O操作不会直接阻塞主应用程序线程。您在主应用程序线程上运行的代码阻止了主应用程序线程。您需要确定在主应用程序线程上运行的代码被绑定的位置。为此,请使用调试器或Log.d()
语句,或其他任何内容。
例如,在大多数Android设备上,文件系统是YAFFS2,它具有每分区全局锁定。引用Brad Fitzpatrick:
yaffs在整个文件系统代码周围有一个巨大的锁定,所以即使是一个微小的stat()也可以阻塞几秒钟,如果磁盘被其他东西锤击(在启动,重同步等)。
因此,如果您在后台线程中将文件系统绑定了几秒钟,主应用程序线程将无法执行自己的文件I / O.也许这就是绊倒你的行为,在这种情况下,Android 2.3中的StrictMode
可以帮助您找出困难的根源。
那么将它移到另一个线程的重点是什么?
重点是将闪存I / O移离主应用程序线程。所有闪存I / O.
FWIW,Android将出现在ext4设备上(例如,Nexus S),这个问题就会消失......尽管你需要担心sync()
电话。在YAFFS2上,sync()
并不那么重要,因为它几乎没有缓冲。