Java - 最有效的随机访问多线程列表

时间:2017-01-10 18:00:41

标签: java multithreading performance list random

选择列表结构:

同步LinkedList。

情境:

我的程序需要在网格中渲染一些(而非计算)生成的图像。这些图像必须在某些数据值发生变化时更新(在另一个线程上),因此,我有一个渲染队列来管理它。

渲染队列是一个同步的LinkedList,在低优先级的线程上,它会不断被迭代以检查某些渲染工作是否需要执行。由于图像基于各种数据,每种数据都可以独立变化,我需要某种形式的队列来组合变化。

数据往往会以块的形式发生变化,所以当一大批批次出现时,我会看到一条想象线沿着重新渲染瓷砖的区域向下运行。为了解决这个问题,我决定不按标准顺序渲染,而是以随机顺序渲染它们(以给出“溶解/输出”效果)。

它看起来很可爱,但唯一的问题是,完成此效果运行所需的时间有明显不同。

问题:

我认为有几个原因是随机访问这个列表而不是迭代会导致这种明显的延迟。首先,随机数生成器的nextInt方法可能占用足够长的时间。其次,由于它是一个LinkedList,当列表的大小在4000s范围内时,获取第n个项目可能也很重要。

我可能忽略了这种延迟的其他原因吗?不是使用随机数生成器,甚至是链表,我还能有效地实现随机访问&从列表中删除?如果你已经阅读了这个场景,也许你可以想到另一种完全可以解决这个问题的方法吗?

要求:

  • 多线程添加到&修改清单。
  • 随机访问&从列表中删除项目。
  • 高效操作,具有大型数据集和运行次数

2 个答案:

答案 0 :(得分:1)

您可以使用ArrayList以及一些简单的操作来非常有效地实现这一点。

  • 要插入,请始终在列表末尾插入新作品(摊销的常量时间操作)。
  • 要提取随机数,请选择一个随机数i,将i处的元素与列表末尾的元素交换,然后提取并返回该新的最后一个元素。

此处的代码(未经测试,未编译):

class RandomizedQueue<T> { 
  private final List<T> workItems = new ArrayList<>();
  private final Random random;

  RandomizedQueue(Random random) {
    this.random = random;
  }

  public synchronized void insert(T item) {
    workItems.add(item);
  }

  public synchronized T extract() {
    if (workItems.isEmpty()) {
      return null;  // or throw an exception
    }

    int pos = random.nextInt(workItems.size());
    int lastPos = workItems.size() - 1;
    T item = workItems.get(pos);
    workItems.set(pos, workItems.get(lastPos));
    return workItems.remove(lastPos);
  }
}

答案 1 :(得分:0)

您可以使用PriorityQueue,并且在向此队列添加内容时为每个项目提供随机优先级。渲染可以始终采用队列中的顶部元素,因为它已经随机化了。在PriorityQueue(或更好的put,具有随机优先级)中的“随机”位置插入非常快。