2012-07-14 60 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

最后。