线程安全地循环遍历 ConcurrentHashMap 而不会阻塞
Thread safely loop through ConcurrentHashMap with no blocking
我正在开发一个超低延迟和高性能的应用程序。
核心是单线程的,不用担心并发问题。
我正在开发一个计划日志功能,它会定期记录消息以防止相同的消息在日志中刷新。
因此日志 class 包含一个 ConcurrentHashMap
,一个线程更新它(放置新键或更新现有值),另一个线程定期循环映射以记录所有消息。
我担心的是,当循环遍历 Map 时需要记录,这可能需要一些时间,它会阻止尝试更新 Map 的线程吗?任何阻塞都是不可接受的,因为我们的应用程序核心是单线程的。
除了 ConcurrentHashMap
之外还有其他数据结构可以用来减少内存占用吗?
有没有一种线程安全的方法可以在只读的情况下迭代 Map 而不会阻塞?即使迭代的数据可能过时仍然可以接受。
根据the java API docs,它说:
[...] even though all operations are thread-safe, retrieval operations do not entail locking [...]
此外,entrySet() 方法文档告诉我们:
The [returned] set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
这意味着在对其进行迭代时可以修改地图,这意味着它确实不会阻塞整个地图。
可能还有其他结构可以让您减少内存占用、减少延迟,并可能提供更统一和一致的性能配置文件。
其中之一是工作模式,您的主要工作人员发布到一个非阻塞队列,而记录器从该队列中提取数据。这应该分离两个进程,允许多个并发发布者并允许您扩展记录器。
一个可能的数据结构是ConcurrentLinked Queue。我对 Java 的经验很少,所以我不确定它的性能配置文件与并发 hashmap 有何不同;但这是分布式系统和 golang 中非常常见的模式。
我正在开发一个超低延迟和高性能的应用程序。 核心是单线程的,不用担心并发问题。
我正在开发一个计划日志功能,它会定期记录消息以防止相同的消息在日志中刷新。
因此日志 class 包含一个 ConcurrentHashMap
,一个线程更新它(放置新键或更新现有值),另一个线程定期循环映射以记录所有消息。
我担心的是,当循环遍历 Map 时需要记录,这可能需要一些时间,它会阻止尝试更新 Map 的线程吗?任何阻塞都是不可接受的,因为我们的应用程序核心是单线程的。
除了 ConcurrentHashMap
之外还有其他数据结构可以用来减少内存占用吗?
有没有一种线程安全的方法可以在只读的情况下迭代 Map 而不会阻塞?即使迭代的数据可能过时仍然可以接受。
根据the java API docs,它说:
[...] even though all operations are thread-safe, retrieval operations do not entail locking [...]
此外,entrySet() 方法文档告诉我们:
The [returned] set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
这意味着在对其进行迭代时可以修改地图,这意味着它确实不会阻塞整个地图。
可能还有其他结构可以让您减少内存占用、减少延迟,并可能提供更统一和一致的性能配置文件。
其中之一是工作模式,您的主要工作人员发布到一个非阻塞队列,而记录器从该队列中提取数据。这应该分离两个进程,允许多个并发发布者并允许您扩展记录器。
一个可能的数据结构是ConcurrentLinked Queue。我对 Java 的经验很少,所以我不确定它的性能配置文件与并发 hashmap 有何不同;但这是分布式系统和 golang 中非常常见的模式。