[英]java.util.ConcurrentModificationException in For loop
[英]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.