循环静态 Set-java

发布于 2024-10-21 08:43:01 字数 810 浏览 2 评论 0原文

我的代码中有:

public static Set<Long> workItemsForTasks = new HashSet<Long>();

它是一个 Web 应用程序,在代码中用户可以向地图添加新项目 - 我在代码中添加如下:

WorkflowOperations.workItemsForTasks.add(workItem.getId());

一旦工作流程到达特定代码,我就会像这样循环遍历地图:

 Iterator workItemsIter = service.workItemsForTasksToBMS.iterator();
   while (workItemsIter.hasNext()) {
workItemsIter.remove();

    ...
    }

我的问题是:

一旦我得到迭代器 - 如果另一个用户向地图添加了一个新项目(因为它不在同一个互联网页面中) - 当我循环它时它会影响地图吗?或者检索迭代器可以确保它保留映射大小直到循环开始的时间?

已编辑

这是一个接受不同 Web 服务调用的 Web 应用程序。

在调用 A 中,用户可能添加在调用 BI 中需要处理的数据。

因此,我定义了一个单例类(通过 spring bean),它保存我需要处理的数据集(数据是数字),并且每次我有 Web 服务调用 A 时,我都会修改该集。一旦用户请求 Web 服务致电 B - 我必须收集到目前为止的数据并用它执行一些操作。

I have in my code:

public static Set<Long> workItemsForTasks = new HashSet<Long>();

It's a web application, and during the code the users can add new items to the map - and I add in the code like this:

WorkflowOperations.workItemsForTasks.add(workItem.getId());

Once the workflow reaches a specific code, I loop over the map like this:

 Iterator workItemsIter = service.workItemsForTasksToBMS.iterator();
   while (workItemsIter.hasNext()) {
workItemsIter.remove();

    ...
    }

My question is:

Once I get the iterator - if another user added a new item to the map (since it's not in the same internet page) - will it influence the map while I loop over it? Or retrieving the iterator ensures me that it holds the map size up to the time that the looping started?

EDITED

It's a web application that accepts different web service calls.

In Call A the users might add data that in Call B I need to handle.

So I defined a singleton class (via spring bean) which holds the Set of data that I need to handle (the data is numbers) and I modify the Set each time that I have web service Call A. once the user asks for web service Call B - I have to collect the data so far and execute something with it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遗失的美好 2024-10-28 08:43:01

是否从多个线程同时访问该集合?

如果这一切都发生在一个线程上,那么你所做的就很好。

但是,如果存在并发访问,那么您就做错了两件事。首先,HashSet 不是线程安全的。其次,在迭代 HashSet 时修改它(通过迭代器除外)是错误的,并且会(希望如此!)产生 ConcurrentModificationException 。

您可以通过考虑 java.util.concurrent 中的类来解决这个问题,或者您也可以将一些您自己的同步添加到您的案例中。您可以同步对集合的访问,并且当您需要从中删除内容时,可以一次性完成所有操作。

private static void doMyStuff() {
    Set<Long> myWorkingSet;
    synchronized (workItemsForTasks) {
        myWorkingSet = new HashSet(workItemsForTasks);
        workItemsForTasks.clear();
    }
    for (long x : myWorkingSet) {
        // do something
    }
}

如果您执行类似的操作,则应将 workItemsForTasks 隐藏在类中的访问方法后面,以便保证正确的同步。

Is the set being accessed concurrently from multiple threads?

If it all happens on one thread, then what you're doing is fine.

However, if there is concurrent access, then you're doing two things wrong. First, HashSet is not thread-safe. Second, modifying a HashSet while iterating over it (except through an Iterator) is wrong, and will (hopefully!) produce a ConcurrentModificationException.

You might address this by considering classes in java.util.concurrent, or you could also add some of your own synchronization to your case. You could synchronize access to the set, and when you need to remove stuff from it, do it all at once.

private static void doMyStuff() {
    Set<Long> myWorkingSet;
    synchronized (workItemsForTasks) {
        myWorkingSet = new HashSet(workItemsForTasks);
        workItemsForTasks.clear();
    }
    for (long x : myWorkingSet) {
        // do something
    }
}

If you do something like this, you should hide workItemsForTasks behind access methods in your class so you can guarantee correct synchronization.

日裸衫吸 2024-10-28 08:43:01

静态通常是一件坏事。每次看到它时,请小心

此代码将在多线程环境中执行,因此您编写的内容将不起作用 - 您将得到 ConcurrentModificationException

you don't have a domain model!多头组没有意义。尝试用更高层次的抽象来表达正在发生的事情。

你没有遵循“告诉不要问”,并且特别违反了 LoD-F (http://pragprog.com/articles/tell-dont-ask) - 这是一种说你的代码很快将很难遵循的方式什么。

或者,要破解大部分有效的功能,请使用 CopyOnWriteArraySet。

static state is generally a bad thing. every time you see it, be wary

this code will be executed in a multithreaded environment, so what you have written will not work - you will get ConcurrentModificationException

you dont have a domain model! sets of longs are not meaningful. try to express what is going on in terms of a higher level abstraction.

you are not following "tell dont ask", and specifically violating LoD-F (http://pragprog.com/articles/tell-dont-ask) - which is a way of saying yur code will soon be difficult to follow who does what.

alternatively, to hack in something that will mostly work, use a CopyOnWriteArraySet.

渡你暖光 2024-10-28 08:43:01

首先,我假设当您说地图时,您实际上是指 设置。根据 Java 文档

请注意,此实现不是同步的。如果是多线程
同时访问一个哈希集,并且至少有一个线程
修改集合,必须在外部同步。这是
通常通过同步某个对象来完成,该对象自然地
封装了集合。如果不存在这样的对象,则该集合应该是
使用 Collections.synchronizedSet 方法“包装”。这是最好的
在创建时完成,以防止意外的不同步访问
套装:

HashSet 的线程安全实现如下:就

Set s = Collections.synchronizedSet(new HashSet(...));

Iterator 而言,在存在不同步并发修改的情况下不可能做出任何硬保证,因此您应该在迭代返回的集合时手动同步返回的集合,否则结果将是不确定的。

Set workItemsForTasks = Collections.synchronizedSet(new HashSet());
synchronized(workItemsForTasks) {
Iterator workItemsIter  = workItemsForTasks.iterator(); //Must be in synchronized block
while (workItemsIter.hasNext())
    //Do Something
}

First of all, am assuming when you said map, you actually meant Set. As per Java Doc,

Note that this implementation is not synchronized. If multiple threads
access a hash set concurrently, and at least one of the threads
modifies the set, it must be synchronized externally. This is
typically accomplished by synchronizing on some object that naturally
encapsulates the set. If no such object exists, the set should be
“wrapped” using the Collections.synchronizedSet method. This is best
done at creation time, to prevent accidental unsynchronized access to
the set:

Thread safe implementation of HashSet would be like:

Set s = Collections.synchronizedSet(new HashSet(...));

As far as Iterator goes, It is impossible to make any hard guarantees in the presence of unsynchronized concurrent modification, so you should manually synchronize on the returned set when iterating over it else the results would be non-deterministic.

Set workItemsForTasks = Collections.synchronizedSet(new HashSet());
synchronized(workItemsForTasks) {
Iterator workItemsIter  = workItemsForTasks.iterator(); //Must be in synchronized block
while (workItemsIter.hasNext())
    //Do Something
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文