【问题标题】:Java -- What is the most efficient way to synchronize an ArrayList?Java——同步 ArrayList 的最有效方法是什么?
【发布时间】:2011-08-17 03:11:39
【问题描述】:

我的程序有一个 OpenGL 渲染线程和一个数据修改线程。渲染线程访问一组 ArrayLists 中的数据,而数据修改线程更改、删除对象并将对象添加到 ArrayLists。线程每秒更新大约 60 次,而 ArrayList 操作是程序的瓶颈。我已经尝试过同步块(超慢)、CopyOnWriteArrayLists(非常慢),以及在渲染线程中创建缓冲区 ArrayLists(三害相权取其轻)。从并发 ArrayList 中获得最大效率的“最佳”方法是什么?

【问题讨论】:

  • “ArrayLists 群”的算法和拓扑你需要多说一些。
  • 您是否考虑过利用ConcurrentHashMapConcurrentSkipListMap/Set
  • 您是否将 java.util.concurrent 包视为同步块的替代方案?
  • 您正在访问/修改什么样的数据?也许有比 ArrayLists 更有效的结构。

标签: java multithreading data-structures synchronization arraylist


【解决方案1】:
List<YourObject> syncList = Collections.synchronizedList(yourList);

【讨论】:

  • 我对这个解决方案非常厌倦。首先,在使用迭代器的时候,集合必须手动同步,可能还有其他问题。我认为这是程序逻辑的问题。
  • 这为您提供了一个全有或全无的解决方案,因为问题是关于尝试实现更高粒度的锁定
  • -1 这根本不能回答问题。事实上,使用 Collection.synchronized* 始终是最便宜、最低效且经常不正确的对集合进行同步的方法。虽然它偶尔可以“完成工作”,但只有在工作并不重要时才可以使用。
【解决方案2】:

最好的机制是让你的工作在 GL 线程和队列中被执行。如果只有一个线程访问该列表,则没有问题。

【讨论】:

  • 为什么最好将程序逻辑迁移到gl线程中?
  • 你在搞乱 GL 状态。所有的状态都应该在 GL 线程中完成。就这么简单。
  • 在Android上,需要先获取surface实例,然后surface.queueEvent(new Runnable() { .... });
  • 看起来他们有两种执行方法:一种是您将自己的渲染代码插入到每帧处理的 GLSurfaceView 中,另一种是您可以发布可运行的执行。对您的通用代码使用第一种方法,它更有效。但是为了从其他线程做一些事情,比如修改 GL 线程“拥有”的列表,你会发布一个 Runnable。然后,当一切都被评估时,包括 GL 更新和发布的可运行文件,没有任何东西会与其他任何东西同时执行。这很简单。
猜你喜欢
  • 2016-03-20
  • 2016-01-18
  • 2018-02-16
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多