- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 JAX-RS API 开发 Java 服务。我决定遵循单例模式,但现在我对如何管理并发有一些疑问。
以下是我的代码的简化示例:
@Singleton
@Path("/")
public class NfvDeployer {
private static Map<String, List<String>> allocatedNodesOnHost;
private static Map<String, String> loadedHosts;
private static Map<String, String> loadedNodes;
...
@POST
@Path("nffgs/{id}/nodes")
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
public MyNode postNodeOnNFFG(MyNode Node, @PathParam("id") String id) {
...
synchronized (this) {
...
allocatedNodesOnHost.get(H).add(Node.ID);
}
}
@GET
@Path("hosts/{id}/nodes")
@Produces(MediaType.APPLICATION_XML)
public MyNodes getNodeFromNFFG(@PathParam("id") String id) {
...
for(String S : allocatedNodesOnHost.get(id)) {
...
}
}
}
您认为这种方法可行吗?所有 GET 请求应同时发生,而 POST 请求应串行化。正确吗?
最佳答案
有些事情可能无法按预期工作。首先,由于您将 NfvDeployer
声明为 @Singleton
,因此您不必严格将所有字段设为静态。由于框架将确保仅存在其中一个,因此应该覆盖它。
关于同步,按原样存在问题。考虑当您写入作为 allocatedNodesOnHost
中的值包含的列表并同时迭代同一列表时的情况。您最终将得到一个ConcurrentModificationException
。来自 Javadoc :
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it.
对此至少有两种解决方案,它们取决于您想要哪种保证。
选项 1:一致的数据 View
假设列表的读者和列表的作者必须对列表有一致的看法。含义:如果有人正在编写新值,则读者无法查看列表中包含的值的稍旧版本。为了解决这个问题,我们应该同步对 map (及其列表值)的所有访问:
public MyNode postNodeOnNFFG(MyNode node, @PathParam("id") String id) {
synchronized (allocatedNodesOnHost) {
allocatedNodesOnHost.get(id).add(node.ID);
}
}
public MyNodes getNodeFromNFFG(@PathParam("id") String id) {
synchronized (allocatedNodesOnHost) {
for(String S : allocatedNodesOnHost.get(id)) {
...
}
}
}
您会注意到,我在 allocatedNodesOnHost
上同步,而不是在 this
上同步。通过在 this
上进行同步,我们获得了一个非常粗粒度的锁,它会影响我们可能设置的任何其他同步块(synchronized block)。再次强调,为了避免 ConcurrentModificationExceptions,所有对 allocatedNodesOnHost
的访问都需要同步。
选项 2:数据 View 不一致
当我说“不一致”时,我并不是说错误,我的意思是它可能稍微过时了,而且仅在并发修改的情况下。本质上,我们将在选项 1 中执行的同步卸载到 JVM 提供的结构中,该结构将为我们完成此操作。
首先,我们将使用 ConcurrentHashMap
声明我们的字段。 :
private Map<String, List<String>> allocatedNodesOnHost = new ConcurrentHashMap<>();
ConcurrentHashMap 为我们提供了一个映射,允许我们读取和写入映射,而无需同步它。它尽可能避免阻塞,因此当您知道将有并发的读取器和写入器时,最好在多线程应用程序中使用它。
当我们在该映射中创建一个值时,我们将使用 CopyOnWriteArrayList
,描述为:
A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array. This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads.
请注意警告:如果您无法/不会同步并且没有频繁的写入者,请使用此选项。如果您不经常写入列表,这是一个可行的选择。
因此,当我们向 allocatedNodesOnHost
映射添加新列表时,我们会这样做:
allocatedNodesOnHost.put(hostName, new CopyOnWriteArrayList<>());
然后我们可以在访问allocatedNodesOnHost
时放弃同步:
public MyNode postNodeOnNFFG(MyNode node, @PathParam("id") String id) {
allocatedNodesOnHost.get(id).add(node.ID);
}
public MyNodes getNodeFromNFFG(@PathParam("id") String id) {
for(String S : allocatedNodesOnHost.get(id)) {
...
}
}
关于java - Java 中的单例服务和多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48356904/
我最近购买了《C 编程语言》并尝试了 Ex 1-8这是代码 #include #include #include /* * */ int main() { int nl,nt,nb;
早上好!我有一个变量“var”,可能为 0。我检查该变量是否为空,如果不是,我将该变量保存在 php session 中,然后调用另一个页面。在这个新页面中,我检查我创建的 session 是否为空,
我正在努力完成 Learn Python the Hard Way ex.25,但我无法理解某些事情。这是脚本: def break_words(stuff): """this functio
我是一名优秀的程序员,十分优秀!