2013-03-10 1 views
0

У меня есть несколько потоков с использованием shared variabled queue. После его обработки (при печати) удаляет элемент из очередиДругой поток удалял элемент из очереди?

protected void tryToPrint() { 
    while (true) { 
     try { 
      if (printer.isAvailable() && printer.isFair(this)) { 
       queueLock.lock(); 
       try { 
        if (queue.isEmpty()) 
         break; 

        printer.requestToPrint(this, queue.get(0)); 
        queue.remove(0); 
        synchronized (System.out) { 
         System.out.println(getName() + " printed. queue size: " + queue.size()); 
        } 
       } finally { 
        queueLock.unlock(); 
       } 
      } else { 
       printer.requestToPrintNext(this); 
      } 
     } catch (IllegalPrintStateException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Но я получаю

Exception in thread "Thread-1" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 
    at java.util.ArrayList.rangeCheck(ArrayList.java:604) 
    at java.util.ArrayList.remove(ArrayList.java:445) 
    at printer.ClientImpl.tryToPrint(ClientImpl.java:34) 
    at printer.AbstractClient.run(AbstractClient.java:28) 
    at java.lang.Thread.run(Thread.java:722) 

Я полагаю, другой поток каким-то образом удаляется элемент из очереди? Как это возможно, я закрыл его?

ОБНОВЛЕНИЕ: очередь на самом деле является ArrayList<File>(). Имеет ли значение, если это не потоковая безопасность? Я заблокировал queueLock?

+0

Каков тип 'queue'? –

+0

@CyrilleKa, его 'ArrayList ()' –

+0

Можете ли вы отправить код для того, что другие потоки могут сделать в очереди? Возможно ли, что один из них не почитает 'queueLock'? – angelatlarge

ответ

1

Что касается вашего конкретного примера, что такое queueLock? Где он создан? Разделяется ли он между потоками (например, static - мое предположение - нет, что может вызвать проблемы)? Нужна дополнительная информация.

Если вы не хотите беспокоиться обо всех этих вопросах, просто перепишите его, используя синхронизированный. Упрощение ...

protected void tryToPrint() { 
    while (true) { 
     try { 
      if (printer.isAvailable() && printer.isFair(this)) { 
       synchronized(queue) { 
        if (queue.isEmpty()) 
         break; 

        printer.requestToPrint(this, queue.get(0)); 
        queue.remove(0); 
        synchronized (System.out) { 
         System.out.println(getName() + " printed. queue size: " + queue.size()); 
        } 
       } 
      } else { 
       printer.requestToPrintNext(this); 
      } 
     } catch (IllegalPrintStateException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

QueueLock - это «ReentrantLock (true)». Я думаю, что ошибка связана с тем, что она не «статична». Определив его как статический, должен ли он быть таким же, как 'synchronized (queue)'? Кажется, я не получаю такой же результат ... настройка - это 3 клиентских потока, запускающих этот код. 1 (сервер), выполняющий роль сервера печати. –

+0

Как-то это похоже на 'printer.requestToPrint (это queue.get (0));' запускается несколько раз, прежде чем system.out печатает объект размера очереди. Как это возможно. Это кажется возможным (менее вероятно, с 'synchronized (queue)'). Это единственный код, который выполняется для клиента. Сервер никоим образом не обращается к очереди. Код находится по адресу http://pastie.org/6438147. Обратите внимание, что я только модифицировал файлы '* Impl.java', остальные - от лектора, поэтому предполагается, что он работает. Это больше интерфейс. –

+0

Если вы используете queueLock, и он не объявлен статическим, это определенно проблема, так как каждый поток блокирует его собственный queueLock. – xagyg

Смежные вопросы