Исключение Броска потоков Java

Я пытаюсь сделать систему проверки в супермаркете, используя темы. У каждого клиента есть идентификатор и время ожидания. Добавьте клиента к оформлению заказа с наименьшим временем ожидания. Время ожидания проверки - это сумма времени ожидания клиентов от этой проверки. Время ожидания в секундах и с каждой секундой уменьшается. Когда время ожидания клиента равно 0, мне нужно удалить его из очереди, и вот проблема. Это бросает исключение

public class Checkout extends Thread{


    public ArrayList<Client> clients = new ArrayList<Client>();
    public ArrayList<Client> deleted = new ArrayList<Client>();
    Iterator<Client> it = clients.iterator();
    int sum=0;
    View v;
    Shop m;

    public Checkout(String nume) {
        setName(nume);
    }

    public void run() {

        try {
                while(true)
                {
                    delete_client();
                    sleep(1000);                
                }
        }catch(InterruptedException e) {
            System.out.println(e.toString());
        }
    }

    public synchronized void add_client(Client c) throws InterruptedException{
        clients.add(c);
        sum=sum+c.getWaintinTime();
        notifyAll();
    }

    public synchronized void delete_client()throws InterruptedException{
        while (clients.size()==0)
            wait();
        while(it.hasNext())
        {
            Client c = it.next();
            if(c.getDecrement()==0)
            {
                v.display("\nTime: "+ m.curentTime +" Client "+Long.toString(c.getID()+1)+" leaved the checkout " + getName());
                deleted.add(c);
            }
            clients.removeAll(deleted);
        }
        notifyAll();
    }

    public synchronized long waiting_time() throws InterruptedException{
        notifyAll();
        return sum;
    }

}

public class Shop extends Thread {

    private Checkout checkout[];
    private int nr_checkouts;
    static int id =0;
    private int nr_clients;
    public int waitingTime; // random from interval (wMin, wMax)
    public int wMax,wMin; //get them from TextFields
    View v;
    Random r = new Random();

    public Shop(View v, int wMin1, int wMax1, int nr_checkouts, Checkout checkout[], String name, int nr_clients) {
        setName(name);
        this.v=v;
        this.wMax=wMax1;
        this.wMin=wMin1;
        this.nr_checkouts = nr_checkouts;
        this.checkout= new Checkout[nr_checkouts];
        this.nr_clients = nr_clients;
        for(int i =0; i<nr_checkouts;i++) {
            this.checkout[i]=checkout[i];
        }
    }

    private int min_index() {
        int index = 0;
        try {
            long min = checkout[0].waiting_time();
            for(int i =1 ; i<nr_case;i++) {
                long lung = casa[i].waiting_time);
                if(lung<min) {
                    min = lung;
                    index = i;
                }
            }
        }catch ( InterruptedException e ) {
            System.out.println(e.toString());
        }
        return index;
    }

     public void run(){ 
             try{
                 int i=0;

                 while( i<nr_clients ){
                     i++;
                     waitingTime = r.nextInt((wMax-wMin)+1)+wMin;
                     Client c = new Client(waitingTime,id++);
                     int m = min_index(); 
                     currentTime++;
                     checkout[m].add_client( c ); //add it ad the checkout with minimum waiting time
                     v.display("\nTime "+ currentTime +" Client " +Long.toString( id )+" | with waiting time  " + waitingTime+" | came at checkout  "+ Integer.toString(m));
                     sleep( 1000 );
                 }
             }
             catch( InterruptedException e ){
                 System.out.println(e.toString());
             }
        }
    }
public class Client {

    private int waitingTime;
    private int id=0;

    public Client(int waitingTime,int id)
    {
        this.id=id;
        this.waitingTime = waitingTime;
    }

    public int getDecrement() {
        return this.waitingTime--;
    }

Я получаю это исключение

Exception in thread "Checkout 1" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at thread.thread.Checkout.delete_client(Checkout.java:55)
at thread.thread.Checkout.run(Checkout.java:35)

Строка 35: delete_client();Строка 55: Client c = it.next();

2 ответа

ConcurrentModificationException генерируется, когда два потока хотят использовать один и тот же ресурс одновременно.

Вы используете ключевое слово synchronized, и это хорошо, но исключение происходит, потому что вы вызываете delete_client внутри того же класса без другого объекта блокировки. Документы Java говорят:

Во-первых, невозможно выполнить два вызова синхронизированных методов для одного и того же объекта. Когда один поток выполняет синхронизированный метод для объекта, все остальные потоки, которые вызывают синхронизированные методы для того же блока объекта (приостанавливают выполнение), пока первый поток не завершится с объектом.

Итак, вы можете сделать следующее:

private final Object countLock = new Object();
.
.
.
while(true)
{
   synchronized (countLock) {
       delete_client();
   }
   sleep(1000);                
}

Когда вы вызываете модифицирующие методы, такие как removeAll при итерации List, это бросит ConcurrentModificationException,

Вы можете сделать это следующим образом:

it = clients.iterator();
while(it.hasNext())
{
    Client c = it.next();
    if(c.getDecrement()==0)
    {
        v.display("\nTime: "+ m.curentTime +" Client "+Long.toString(c.getID()+1)+" leaved the checkout " + getName());
        deleted.add(c);
        it.remove();
    }
}
Другие вопросы по тегам