我正在寻找一个解决问题的方法,我想象是相当简单,但不能弄清楚一些原因。因为我刚刚开始编程几个星期前,我敢肯定,这段代码可能有点不完美的书面,所以请容忍我。
我的问题与代码,是它抛出一个异常在for循环“for(Bestellung bestellung:bestellungenInProduktion){”(代码的下三分之一;标记注解)只要我同时“提交”3个或更多的“订单”,而当同时只提交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个订单,所以我希望它也可以处理更多订单,但似乎有一个同步问题,我找不到解决方案。
我尝试使用迭代器(我用不同的方法尝试了很多个小时),以及添加睡眠(在单独的类中;在其他地方都有效)在不同的地方持续不同的时间(因为那之前已经为我解决了一些问题),所有这些都没有起作用。
不幸的是,如果不使用LinkedList,就意味着我的代码几乎要从头开始,因此,如果可能的话,我希望用另一种解决方法来解决这个问题。
如果有人能帮助我或给我指出正确的方向,我将不胜感激。如果需要任何进一步的信息,我一定会尽快添加到这个帖子。
1条答案
按热度按时间7hiiyaii1#
如果我理解正确的话,你有一个
for
循环遍历一个列表(bestellungInProduktion
),在这个循环中,你调用列表上的List::remove
,这将导致ConcurrentModificationException
,正如预期的那样。在内部,增强的
for
循环在该列表上创建了一个迭代器,并且通过从列表中删除(或添加)一个元素,该迭代器将失去同步。如果你想从列表中删除一个你正在迭代的条目,你必须调用
Iterator::remove
: