另一个线程从队列中删除了元素

时间:2013-03-10 03:33:22

标签: java multithreading concurrency

我有多个线程使用共享变量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

1 个答案:

答案 0 :(得分:1)

关于您的具体示例,什么是queueLock?它在哪里创建?是否在线程之间共享(例如静态 - 我的猜测是否定,这可能导致您的问题)?需要更多信息。

如果您不想担心所有这些问题,那么只需使用synchronized重写即可。更简单...

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();
        }
    }
}