简体   繁体   English

将项目添加到另一个线程中的列表时进行CheckForComodification

[英]CheckForComodification when adding items to list in another thread

Hey I am modifying the class called SimpleBalls from this answer (the lower one). 嘿,我正在从这个答案 (下一个)中修改名为SimpleBalls的类。 In the original version all the items in the list are being added by ballsUp.add(new Ball() before the animation takes place. 在原始版本中,动画发生之前, ballsUp.add(new Ball()将添加列表中的所有项目。

However, I want to dynamically add balls depending on some console output happening in another thread. 但是,我想根据另一个线程中发生的某些控制台输出来动态添加球。 This, of course, leads to comodification as the animation methods and me adding Ball s will often access the list at the same time. 当然,这会导致协同修改,因为动画方法和我添加Ball经常会同时访问列表。

I tried setting my list to Collections.synchronizedList but I think it only had an effect to the "upper part" of the program as, just above the BounceEngine class we have 我尝试将列表设置为Collections.synchronizedList但我认为它仅对程序的“上部” BounceEngine ,就像在我们拥有的BounceEngine类之上

public List<Ball> getBalls() {
            return ballsUp;
        }

set up for the iterations and I don't really know how to apply this there. 设置迭代,我真的不知道如何在此应用。 Also, the same applies to synchronized(list) as neither ballsUp (which is the "real" List name), Ball nor getBalls() can be passed as an argument to synchronized() . 另外,对ballsUp ,因为不得将ballsUp (这是“真实的”列表名称), BallgetBalls()都可以作为参数传递给getBalls() ,这也适用于synchronized(list) synchronized()

This is how I am adding new Balls: 这就是我添加新球的方式:

  Runnable r = new Runnable() {
            public void run() {

          String s = null;
             try {
              while ((s = stdInput.readLine()) != null) {
               if(s.startsWith("sttest")){
                ballsUp.add(new Ball(new Color(random(200)+54, random(200)+54, random(200)+54)));
                           }
                    }
            }
        };

        new Thread(r).start();

Removing the ballsUp.add makes the code code seamlessly. 删除ballsUp.add将使代码无缝地编码。

The rest of the class is pretty much the same, the only major change is the Thread calling the add . 该类的其余部分几乎相同,唯一的主要变化是Thread调用add

UPDATE: I was able to narrow down the problem a bit. 更新:我能够缩小范围。 No matter with what I "wrap" it, the add won't work if inside the while ((s = stdInput.readLine()) != null) . 无论我用什么“包装”,如果在while内((s = stdInput.readLine()) != null)add都将无法工作。 Even when I only run this add once the ball still won't appear. 即使当我只运行此add时,球仍然不会出现。 If I place it below or above the while statement it works perfectly fine, the thread itself or the try/catch doesn't seem to be the error, it's something with the while loop (or its condition) 如果我将其放置在while语句的下方或上方, while它工作得非常好,线程本身或try / catch似乎不是错误,这是while循环(或其条件)引起的

What triggers the error now is the line shown in the screenshot 现在触发错误的是屏幕截图中显示的行 在此处输入图片说明

  • but only if the ballsUp.add(new Ball() is under the hood of the while loop 但仅当ballsUp.add(new Ball()在while循环的ballsUp.add(new Ball()

在此处输入图片说明

Also, SwingUtilities.invokeLater applied to the for loop in the upper picture results in no ball being drawn at all. 同样,将SwingUtilities.invokeLater应用于上图中的for循环会导致根本没有绘制球。

Just make sure the list is always accessed from a single thread: the event dispatch thread: 只要确保始终从单个线程访问该列表即可:事件调度线程:

if (s.startsWith("sttest")) {
    SwingUtilities.invokeLater(() -> ballsUp.add(new Ball(new Color(random(200)+54, random(200)+54, random(200)+54))));
}

You wouldn't have to care about that (because it would happen automatically), if you added a ball to the list as a consequence of a UI event (like a button click): the event would be handled from the event dispatch thread directly. 如果您是由于UI事件(例如单击按钮)而将球添加到列表中,则不必担心(因为它会自动发生):该事件将直接从事件分发线程处理。

You could return a copy of the list: 您可以返回列表的副本

public List<Ball> getBalls() {
    return new ArrayList(ballsUp);
}

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

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