当前位置: 首页 > 知识库问答 >
问题:

Android位图多线程处理-线程不安全?

巫马令
2023-03-14

我想在我的Android应用程序中处理位图——位图可能很大,所以我使用多线程来执行更快的操作。以下是我的代码(Runnable child的一部分):

@Override
public void run() {
    int imageHeight = filter.getBitmap().getHeight();
    int start = threadNumber * imageHeight / threadCount;
    int stop = (threadNumber + 1) * imageHeight / threadCount;
    for (int j = start; j < stop; j++) {
        filter.processLine(j);
    }
}
//...
protected void processLine(int lineNumber)
{
    int width = bitmap.getWidth();
    int pixels[] = new int[width];
    bitmap.getPixels(pixels, 0, width, 0, lineNumber, width, 1);
    for (int i = 0; i < width; i++) {
        pixels[i] = processPixel(pixels[i]);
    }
    bitmap.setPixels(pixels, 0, width, 0, lineNumber, width, 1);
}

当我只使用池中的一个线程时,一切正常。不幸的是,当我使用的线程数等于处理器的内核数(在我的设备中为4)时,结果如下(对于灰度过滤器):

有时看起来像:

  • bitmap.get像素(...)不起作用,因为输出中有黑线
  • bitmap.set像素(...)不起作用,因为输出中有不变的行

我说得对吗?这些函数是线程不安全的吗?我应该如何执行多线程位图过滤才能快速和线程安全?

共有1个答案

卫招
2023-03-14

Android中的2D图像处理由Skia库提供,Chrome也使用该库。

很难找到明确的答案。“Skia不是线程安全的,尽管SkBitmap[由位图使用]是线程安全的……”我不知道该怎么想。我仔细阅读了一堆难以理解的JNI/C代码,这是我能提供的最好的(这似乎比任何人都能做到):

我想你应该调用位图。getPixels()显示整个位图。然后将生成的数组分割,并执行线程处理。所有线程完成后,重新组合结果并调用bitmap。setPixels()

看起来像是位图。getPixels()和位图。setPixels()应该只不过是memcpy()s,但在引用计数、图像缓存、颜色空间转换、预乘以及谁知道其他方面,还有很多事情要做。将Bitmap方法从并行处理中移除应该可以避免麻烦。

 类似资料:
  • 问题内容: 我试图理解多处理比线程的优势。我知道多处理绕过了全局解释器锁,但是还有什么其他优点,线程不能做同样的事情? 问题答案: 该模块使用线程,该模块使用进程。不同之处在于线程在相同的内存空间中运行,而进程具有单独的内存。这使得在具有多处理的进程之间共享对象更加困难。由于线程使用相同的内存,因此必须采取预防措施,否则两个线程将同时写入同一内​​存。这就是全局解释器锁的作用。 生成过程比生成线程

  • null 我更新了我的步骤并添加了一个ThreadPoolTaskExecutor,如下所示 在此之后,我的处理器将被多个线程调用,但使用相同的源数据。我还有什么需要做的吗?

  • 我正在尝试用Python编写一个程序。我想写的是一个脚本,它会立即向用户返回一条友好的消息,但会在后台生成一个长的子进程,它会处理几个不同的文件,并将它们写入一个祖父文件。我已经做了一些关于线程和处理的教程,但我遇到的是,无论我尝试什么,程序都会一直等待,直到子进程完成,然后才会向用户显示前面提到的友好消息。以下是我尝试过的: 线程示例: 我读过这些关于多线程的SO帖子如何在Python中使用线程

  • 我正在尝试使用多个处理器类在处理器步骤中处理记录。这些类可以并行工作。目前我已经编写了一个多线程步骤,其中我 设置处理器类的输入和输出行 提交给遗嘱执行人服务 获取所有未来对象并收集最终输出

  • 我找到了关于线程安全的代码,但它没有来自给出示例的人的任何解释。我想知道为什么如果我不在“count”之前设置“synchronized”变量,那么count值将是非原子的(总是=200是期望的结果)。谢谢

  • 我知道这里之前有人问过这个问题:Kafka流并发? 但这对我来说很奇怪。根据文档(或者我可能遗漏了什么),每个分区都有一个任务,这意味着不同的处理器实例,每个任务由不同的线程执行。但是当我测试它的时候,我看到不同的线程可以得到不同的处理器实例。因此,如果你想在处理器中保持内存状态(老式的方式),你必须锁定? 线程ID:88 ID:c667e669-9023-494b-9345-236777e9df