2012-07-14 44 views
1

我曾經在一個項目中的以下設計調用函數卡住了,但監視器似乎被釋放,怎麼樣?

  • 多個爬蟲
  • 對發現的圖像列表ImageListObservable);這將得到更新線程進程(因此並行)
  • 兩名觀察員收聽列表(DownloaderImagesWindow);警告:這些可以被通知多次,因爲列表得到由線程更新

我一直想只從ImageList最新的條目,所以我用計數器實現它:

public class ImageList extends Observable { 
    private final ConcurrentMap<Integer, Image> images = new ConcurrentHashMap<Integer, Image>(); 
    private final AtomicInteger counter = new AtomicInteger(0); 

    /* There is some more code within here, but its not that important 
     important is that stuff gets added to the list and the list shall 
     inform all listeners about the change 

     The observers then check which is the newest ID in the list (often +1 
     but I guess I will reduce the inform frequency somehow) 
     and call (in synchronized method): 

     int lastIndex = list.getCurrentLastIndex(); 
     getImagesFromTo(myNextValue, lastIndex); 
     myNextValue = lastIndex + 1; 
    */ 

    public synchronized void addToFinished(Image job) throws InterruptedException { 
     int currentCounter = counter.incrementAndGet(); 

     images.put(currentCounter, job); 

     this.setChanged(); 
     this.notifyObservers(); 
    } 

    public synchronized int getCurrentLastIndex() { 
     return counter.get(); 
    } 

    public ArrayList<Image> getImagesFromTo(int starting, int ending) { 
     ArrayList<Image> newImages = new ArrayList<Image>(); 

     Image image; 
     for (int i = starting; i <= ending; i++) { 
      image = images.get(i); 
      if (image != null) { 
       newImages.add(image); 
      } 
     } 

     return newImages; 
    } 
} 

觀察員(Downloader這裏)使用此方法是這樣的:

@Override 
public void update(Observable o, Object arg) { 
    System.out.println("Updated downloader"); 

    if (o instanceof ImageList) { 
     ImageList list = (ImageList) o; 
     downloadNewImages(list); 
    } 
} 

private synchronized void downloadNewImages(ImageList list) { 
    int last = list.getCurrentLastIndex(); 

    for (Image image : list.getImagesFromTo(readImageFrom, last)) { 
     // code gets stuck after this line 
     if (filter.isOk(image)) { 
      // and before this line 
      // [here was a line, but it also fails if I remove it] 
     } 
    } 

    // set the index to the new index 
    readImageFrom = last + 1; 
} 

但是,有時循環卡和第二個電話似乎這是允許的方法。然後,這是發生了什麼:

  • 下載獲取圖像70至70
  • 下載獲取圖像70至71
  • 下載獲取圖像70至72
  • ...
  • 下載獲取圖像70到n

因此,允許第二次調用方法進入方法,但計數器readImageFrom永遠不會更新。

當我在循環中刪除對其他函數的兩個調用時,腳本開始工作。我知道它們不是同步的,但是如果已經同步「父」,它們是否必須是?

filter.isOK()是這樣實現的(其它功能只是返回true或false;當我有包括hasRightColor代碼失敗了,我猜是因爲它是一個慢一點來計算):

public boolean isOk(Image image) { 
    return hasRightDimensions(image) && hasRightColor(image); 
} 

怎麼可以這樣發生? Eclipse不顯示任何拋出的異常(這當然會導致方法退出)。

也許還有一個完全不同的方法來獲取多個觀察者列表中最新的內容(其中每個觀察者可能是多次通知,因爲程序並行運行)?

+0

哪個類包含'downloadNewImages'方法?這個班有多少個實例? readImageFrom聲明在哪裏? – jtoberon 2012-07-14 12:26:20

+0

'downloadNewImages'包含在'Downloader'(兩個觀察者之一)中。只有一個「Downloader」實例(以及另一個觀察者「ImagesWindow」的實例)。 ''readImageFrom''在每個觀察者中被聲明一次(意思是''Downloader''有一個'readImageFrom'''' ImagesWindow''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''')。 – Aufziehvogel 2012-07-14 12:33:20

回答

0

好的,錯誤是一些惡作劇NullPointerException這是沒有顯示給我(誰知道爲什麼)在filter.isOk()

我沒能看到它在我的IDE,因爲我已經從this.image改爲參數傳遞image,但忘了刪除private image頁眉和改變最後的三個函數的參數。

因此,eclipse沒有說任何關於失蹤image,也沒有關於一個未使用的this.image

最後。