我跳到了Android项目,它分配了很多Bitmaps。我在那里遇到了这段代码:
System.gc();
try {
b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e) {
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
log.error("Failed to sleep.");
}
try {
b = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
} catch (OutOfMemoryError e1) {
log.error("Error", e1);
}
}
我开始想知道在调用 System.gc() 后让线程休眠一段时间是否有任何意义? 我自己对 System.gc() 做了一些研究,发现了一些关于它如何工作的信息:
Patrick Dubroy据说在 Android >= Honeycomb 上垃圾收集大约需要 5ms(已优化且并发)。
此外,在一些地方我发现了信息,调用 System.gc() 只是运行垃圾收集器的建议。上面的代码是过去两年增强的项目的一部分,我认为这个 Thread.sleep 是针对此时出现的问题的一些解决方法。
有什么想法吗?
最佳答案
看起来 Thread.Sleep()
被调用,以便在发生 OutOfMemoryError< 时尝试重新创建
第一次尝试时就发生了。第二次尝试时,使用较低的标准来消耗更少的内存:Bitmap
之前为垃圾收集器提供足够的时间来完成其工作RGB_565
而不是 ARGB_8888
。
在第一次尝试创建Bitmap
之前测试可用内存量会更好(对于并发应用程序来说更高效/更容易读取/更强/更少危险),而不是捕获内存不足错误
。
Thread.sleep(100)
则假设垃圾收集将启动并在 100 毫秒内完成,这绝对是任意的。它可能还没有开始,可能仍在运行......
无论如何,调用 System.gc() 在这里没有帮助,因为垃圾无论如何都会被收集。虚拟机会检测到这一点,并且如果有大量垃圾需要收集,则不会等待。
所以我的建议是:
- 忘记这些
System.gc()
和Thread.Sleep()
调用。他们效率低下/乐于助人。 - 在首次尝试创建
位图
之前测试可用内存量。您可以确定 future 生成的位图的大小,因为您知道它的大小和编码。 (引用: Runtime 和 ActivityManager ) - 如果剩余内存量较低,如果生成的
位图
适合(16 位 RGB 而不是 32 位 ARGB),为什么不降低标准。 - 如果这还不够,记录错误和/或显示警报(取决于您的应用,我不知道上下文)就可以了。
Android 团队的两篇有趣的相关文章:
关于android - 在处理位图时调用 System.gc() 和 Thread.sleep() 是否有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23673642/