Исключение Броска потоков 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();
}
}