2013-03-10 58 views
0

我有多個線程使用共享變量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) 

我想另一個線程莫名其妙地刪除從隊列中的元素?我怎麼可能鎖定它?

UPDATE:隊列實際上是ArrayList<File>()。如果它不是線程安全的,它是否重要?我確實鎖定了queueLock

+0

'queue'的類型是什麼? – 2013-03-10 03:38:24

+0

@CyrilleKa,它的'ArrayList ()' – 2013-03-10 03:49:42

+0

你可以發佈其他線程可能對隊列做什麼的代碼嗎?是否有可能其中一個不遵守'queueLock'? – angelatlarge 2013-03-10 04:07:12

回答

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

QueueLock是一個'ReentrantLock(true)'。我認爲這個錯誤是因爲它不是'靜態'。將它定義爲靜態後,它應該與'synchronized(queue)'相同嗎?我似乎沒有得到相同的結果...設置是運行此代碼的3個客戶端線程。 1個打印機(服務器)線程充當打印服務器。 – 2013-03-10 06:58:24

+0

不知怎的,它看起來像'printer.requestToPrint(this,queue.get(0));'是在system.out打印隊列大小之前多次運行的。這怎麼可能。這似乎是可能的(「同步(隊列)」不太可能)。這是爲客戶端運行的唯一代碼。服務器不以任何方式訪問隊列。代碼位於http://pastie.org/6438147。請注意,我只修改了其餘的來自講師的'* Impl.java'文件,因此假定這些文件正在工作。它更多的是一個界面。 – 2013-03-10 06:59:54

+0

如果使用queueLock並且它沒有聲明爲static,那麼肯定是一個問題,因爲每個線程都會鎖定它自己的queueLock。 – xagyg 2013-03-10 09:50:54

相關問題