简体   繁体   English

如何在 java 中同时添加和删除 collections 中的元素?

[英]how to add and remove elements in collections simultaneously in java?

I am trying to add elements and remove the elements in the list simultaneously.我正在尝试同时添加元素并删除列表中的元素。 How to fix this problem?如何解决这个问题?

public class Main3 {
    public static void main(String[] args) throws InterruptedException {
        Vector<Integer> list = new Vector<>();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                list.add(i);
                System.out.println("add " + i);
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("removed " + i);
                list.remove(i);
            }
        });
        t2.start();
    }
}
    

I get the following output:我得到以下 output:

**Error**

add 0
add 1
add 2
add 3
add 4
add 5
add 6
add 7
removed 0
add 8
add 9
removed 1
removed 2
removed 3
removed 4
removed 5
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 5
    at java.base/java.util.Vector.remove(Vector.java:875)
    at com.zoho.Main3.lambda$1(Main3.java:23)
    at java.base/java.lang.Thread.run(Thread.java:829)

The first problem:第一个问题:

As you see from the comments, by using a for loop on your remove section, you are trying to remove a non-existing item.正如您从评论中看到的那样,通过在您的删除部分使用 for 循环,您正在尝试删除一个不存在的项目。

What is going on?到底是怎么回事?

Let's talk sheep.先说羊吧。

You have 10 sheep, and each has a number 0 - 9. Your task is to remove all the sheep.你有 10 只羊,每只羊都有一个数字 0 - 9。你的任务是移走所有的羊。

Since you are a Software developer and are afraid you might lose track, you decide to keep an index.由于您是一名软件开发人员,并且担心您可能会迷失方向,因此您决定保留索引。 You put your index on 0 and start removing sheep;您将索引设置为 0 并开始移除绵羊; after you remove a sheep, you make the index 1 more until you reach number 9.移除一只绵羊后,您将索引设为 1,直到达到第 9 位。

You start by removing First sheep (Number 0).您首先移除第一只羊(编号 0)。 Here, however, is the catch, every time you remove a sheep, they all get assigned a new Number.然而,这里有一个问题,每次你移走一只羊,它们都会被分配一个新的数字。

Sheep 0 is gone,
Sheep 1 becomes 0, 
Sheep 2 becomes 1... 

But the problem is that you don't update your index.但问题是你没有更新你的索引。

So all the rounds go well -> until you are trying to remove Sheep 5 .所以所有的回合 go 都很好 -> 直到你试图删除Sheep 5 Sheep 5 does not exist.羊 5 不存在。 Since the highest Sheep Number is only 4.因为最高的绵羊数只有 4 只。

Since there IS no sheep, you grab nothing and remove nothing and get confused:)既然没有羊,你什么也抓不到,什么也拿不走,然后糊涂了:)

How to solve it?如何解决?

You might be thinking;你可能在想; I will update my index after every round.我会在每一轮之后更新我的索引。 NO NO NO!不不不! Bad practice:) Good for you for not doing that.不好的做法:) 不这样做对你有好处。

Let's just use some different logic instead of keeping an index.让我们使用一些不同的逻辑而不是保留索引。 You do the following.您执行以下操作。 Always remove the last sheep until there are non left.总是移走最后一只羊,直到没有剩下的为止。 Why the last?为什么是最后一个? If we remove the last, we don't even need to rename them after every round:) Super handy.如果我们删除最后一个,我们甚至不需要在每一轮之后重命名它们:) 超级方便。 In programming terms, let's use a while (list.size() > 0) instead of a for-loop/index.在编程术语中,让我们使用 while (list.size() > 0) 代替 for 循环/索引。

Second problem第二个问题

Since the two threads (workers) run at the same time.由于两个线程(工作者)同时运行。 You may remove sheep faster than someone else can add them.您可以比其他人添加羊更快地移除羊。 Therefore, The remove worker can remove one sheep and then say: Wow, no sheep left, done for the day... As he leaves the farm, you add nine other sheep.因此,移走工人可以移走一只羊,然后说:哇,没有羊了,今天结束了……当他离开农场时,你又添加了九只羊。

To solve this, we tell the Remove worker only to start when all the sheep has been added.为了解决这个问题,我们告诉 Remove worker 仅在添加了所有羊后才开始。 We can do this by simply calling a join on the first thread.我们可以通过简单地在第一个线程上调用一个连接来做到这一点。 (Seee code below) (见下面的代码)

Now - you might think - what on earth is the advantage of using concurrency?现在——你可能会想——使用并发到底有什么好处? Well, you can have multiple Remove workers and multiple Add workers: your CPU is literally the limit:)好吧,你可以有多个 Remove 工人和多个 Add 工人:你的 CPU 确实是极限:)

The code as explained解释的代码

public static void main(String[] args) throws InterruptedException {
    Vector<Integer> list = new Vector<>();
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            list.add(i);
            System.out.println("add " + i);
        }
    });
    t1.start();
    t1.join();

    Thread t2 = new Thread(() -> {
        while (list.size() > 0) {
            System.out.println("removed t2");
            list.remove(list.size() - 1);
        }
    });
    t2.start();
}

Final remark:最后的评论:

And here the fun begins... You will soon discover: Some sheep starving, workers waiting for each other forever, some workers holding on to sheep too long... Enjoy:)乐趣从这里开始……你很快就会发现:有些羊饿死了,工人永远在等待,有些工人抓羊太久了……享受吧:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM