繁体   English   中英

在 Java 中的运行方法中对 LinkedList 实施 for 循环:java.util.ConcurrentModificationException

[英]Implementing a for-loop over a LinkedList in a run method in Java: java.util.ConcurrentModificationException

我正在寻找一个我认为相当简单但由于某种原因无法弄清楚的问题的解决方案。 由于我几周前才开始编程,我确信这段代码可能写得不够完美,所以请多多包涵。

我对代码的问题是,一旦我“提交”3 个或更多“for (Bestellung bestellung: bestellungenInProduktion){”(代码的下三分之一;标有注释),它就会在 for 循环中引发异常订单”,而当仅同时提交 1 或 2 个订单时它运行得非常好。

当提交 3 个或更多订单时,第一个订单顺利通过,但在第一个订单的生产完成后立即抛出异常。 错误信息是:

Exception in thread "Thread-0" java.util.ConcurrentModificationException
    at java.base/java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:970)
    at java.base/java.util.LinkedList$ListItr.next(LinkedList.java:892)
    at Produktions_Manager.run(Produktions_Manager.java:88)

这是有问题的代码(异常抛出行大约比最后一行高 25 行):

public class Produktions_Manager extends Thread
{
    // Initiates all instant variables. 
    private Holzbearbeitungs_Roboter holzroboter; // robots
    private Montage_Roboter montageroboter;
    private Lackier_Roboter lackierroboter;
    private Verpackungs_Roboter verpackungsroboter;

    private Fabrik meineFabrik; //myFactory
    private Lager meinLager; //myStorage
    
    private LinkedList<Bestellung> zuVerarbeitendeBestellungen; //ordersToBeCompleted
    private LinkedList<Bestellung> bestellungenInProduktion; //ordersInProduction

    /**
     * The constructor of the Produktions_Manager class instantiates and starts
     * all robots. In also opens the LinkedLists for the orders to be processed
     * and for the orders in production.
     * 
     * @param   meineFabrik   die Fabrik, die eröffnet wird
     * @param   meinLager     das Lager, das eröffnet wird
     */
    public Produktions_Manager(Fabrik meineFabrik, Lager meinLager)
    {
        holzroboter = new Holzbearbeitungs_Roboter("Holzroboter");
        montageroboter = new Montage_Roboter("Montageroboter");
        lackierroboter = new Lackier_Roboter("Lackierroboter");
        verpackungsroboter = new Verpackungs_Roboter("Verpackungsroboter");
        
        holzroboter.start();
        montageroboter.start();
        lackierroboter.start();
        verpackungsroboter.start();

        this.meineFabrik = meineFabrik;
        this.meinLager = meinLager;        
        
        zuVerarbeitendeBestellungen = new LinkedList<Bestellung>();
        bestellungenInProduktion = new LinkedList<Bestellung>();
    }
    
    /**
     * This method checks in an infinite loop if a new order has arrived.
     * If an order has been received, it is removed from the list of orders to be processed
     * and added to the list of products to be produced. Subsequently, the production is started.
     */


    @Override public void run()
    {
        ThreadUtil.syncedPrintln("Produktionsmanager wurde gestartet");
        
        while (true){    //When a new order has arrived, then get the next order and start production.

            Bestellung naechsteBestellung = zuVerarbeitendeBestellungen.peek();
            
            if(naechsteBestellung == null){
                ThreadUtil.syncedPrintln("[Produktions_Manager] keine Bestellung zu verarbeiten");
            } else {
                ThreadUtil.syncedPrintln("[Produktions_Manager] neue Bestellung zu verarbeiten");
            }
                        
            if(naechsteBestellung != null && meinLager.lagerbestandPruefenUndNachbestellen(naechsteBestellung)){
                naechsteBestellung = zuVerarbeitendeBestellungen.poll();          
                bestellungenInProduktion.add(naechsteBestellung); 
                naechsteBestellung.setzeBestellstatus(2);
                
                ThreadUtil.syncedPrintln("[Produktions_Manager] startet die Produktion von " + naechsteBestellung.gibBestellungsNr());
                
                for(Produkt produkt : naechsteBestellung.liefereBestellteProdukte()){
                    roboterzuweisung(produkt);
                    produkt.naechsteProduktionsstation();
                }
            }
            
            //The next line is where the exception is thrown.

            for (Bestellung bestellung : bestellungenInProduktion){ //Order order : ordersInProduction
                boolean alleProdukteProduziert = true; //allItemsProduced
                for(Produkt produkt : bestellung.liefereBestellteProdukte()){ //order.deliverOrdererItems
                    if(produkt.gibAktuellenZustand()!=3){ //product.giveCurrentState
                        alleProdukteProduziert = false; //allItemsProduced
                        break;
                    }
                }
                
                if(alleProdukteProduziert == true){
                 bestellungenInProduktion.remove(bestellung);
                 bestellung.setzeAlleProdukteProduziert();
                 
                }
            }

            //Zusätzliche Meldung, falls keine Bestellungen in der Produktions-Pipeline stehen
            if(bestellungenInProduktion.size() == 0){
                ThreadUtil.syncedPrintln("[Produktions_Manager] keine neuen Bestellungen für Produktion - Roboter können nichts produzieren.");
            } else {
                ThreadUtil.syncedPrintln("[Produktions_Manager] es sind noch Bestellungen in Produktion.");
            }
            
            ThreadUtil.sleep(5000);
            
        }
    }
}

因为它适用于同时提交的 1 个和 2 个订单,我希望它也能处理更多订单,但似乎存在同步问题,我找不到解决方案。

我尝试使用迭代器(我以不同的方式尝试了好几个小时),并在不同的地方添加了不同持续时间的睡眠(在单独的 class 中;在其他任何地方都有效)(因为这之前已经为我解决了一些问题),所有这些都没有奏效。

不幸的是,不使用 LinkedList 意味着几乎要从头开始我的代码,因此如果可能的话,我想用另一种解决方法来解决这个问题。

如果有人能帮助我或指出正确的方向,我将不胜感激。 如果需要任何进一步的信息,我会确保尽快将其添加到这篇文章中。

如果我做对了,您将在列表 ( bestellungInProduktion ) 上有一个for循环,并在该循环内调用该列表上的remove 正如预期的那样,这将导致ConcurrentModificationException

在内部,增强for循环在该列表上创建一个迭代器,并且通过从列表中删除(或添加)一个元素将 go 不同步。

如果你想从你当前迭代的列表中删除一个条目,你必须调用Iterator::remove

for( final var i = bestellungenInProduktion.listIterator(); i.hasNext(); )
{ 
  var alleProdukteProduziert = true;
  final var bestellung = i.next;
  for( final var produkt : bestellung.liefereBestellteProdukte() )
  { 
    if( produkt.gibAktuellenZustand() != 3 )
    {
      alleProdukteProduziert = false;
      break;
    }
  }
                
  if( alleProdukteProduziert )
  {
    i.remove();
    bestellung.setzeAlleProdukteProduziert();
  }
}

暂无
暂无

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

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