在Bitmaps上工作时调用System.gc()和Thread.sleep()是否有意义?

时间:2014-05-15 08:59:50

标签: android bitmap garbage-collection

我已经跳转到Android项目,该项目分配了大量的位图。我在那里遇到了这段代码:

  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()之后暂停Thread一段时间是否有任何意义? 我自己做了一些关于System.gc()的研究,我发现它的工作原理很少:

Patrick Dubroy表示Android上的垃圾收集> = Honeycomb需要大约5毫秒(它已经过优化和并发)。

此外,在很少的地方我找到了信息,调用System.gc()只是一个运行垃圾收集器的建议。上面的代码是项目的一部分,在过去的两年里得到了增强,我想这个Thread.sleep是针对此时出现的问题的一些解决方法。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

看起来Thread.Sleep()被调用,为垃圾收集器提供足够的时间来完成其工作,如果在第一次尝试时发生Bitmap,则尝试重新创建OutOfMemoryError。在第二次尝试时,使用较低的标准来消耗较少的内存:RGB_565而不是ARGB_8888

在第一次尝试创建Bitmap之前测试可用内存量会更好(更高效/更容易读取/更强/更低危险并发应用程序),而不是捕获{{1 }}。

OutOfMemoryError,就其本身而言,假定垃圾收集将在100毫秒内完成并完成,这绝对是任意的。它可能尚未开始,它可能仍在运行......

无论如何,调用Thread.sleep(100)在这里没有用,因为无论如何都会收集垃圾。如果有大量垃圾需要收集,VM会检测到并且不会等待。

所以我的建议是:

  • 忘记这些System.gc()System.gc()来电。他们没有效率/乐于助人。
  • 在第一次尝试创建Thread.Sleep()之前测试可用内存量。您可以确定未来的大小Bitmap,因为您知道它的大小和编码。 (参考:RuntimeActivityManager
  • 如果剩余的内存量很少,为什么不降低标准,如果生成的Bitmap适合(16位RGB而不是32位ARGB)。
  • 如果效率不高,请记录错误和/或显示提醒(取决于您的应用,我不知道上下文)没问题。

Android团队的两篇有趣的相关文章:

答案 1 :(得分:1)

谢谢Shlublu提示可以解决什么问题:)我已经决定减少Thread.sleep两次 - 50ms就足够了。此外,我只在开始时调用System.gc(),因为从我看到的情况来看,当createBitmap失败时没有分配内存 - 所以每次发生OOMException时调用Garbage Collector都没有意义。这是我最终得到的代码。从特征的角度来看,它只是一种重构,但也许对某人有用。

public static Bitmap allocateBitmap(int width, int height) {
 Bitmap bitmap = null;
 System.gc();
 try {
   Thread.sleep(50);
   bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
 } catch (OutOfMemoryError e8888) {
     // error log
   try {
     bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
   } catch (OutOfMemoryError e565) {
     // error log
   }
 } catch (InterruptedException e) {
   log.error("Failed to sleep", e);
 } finally {
   return bitmap;
 }
}