对函数的调用卡住了,但监视器似乎被释放了,怎么办? [英] Call to function gets stuck, but monitor seems to get freed, how?

查看:58
本文介绍了对函数的调用卡住了,但监视器似乎被释放了,怎么办?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个项目中有以下设计

I have the following design in a project

  • 多个爬虫
  • 找到图像的列表ImageList(Observable);这由线程进程更新(因此是并行的)
  • 两个监听列表的观察者(DownloaderImagesWindow);警告:这些可以多次通知,因为列表由线程更新
  • Multiple crawlers
  • a list ImageList for found images (Observable); this gets updated by threaded processes (thus parallel)
  • two observers which listen to the list (Downloader and ImagesWindow); caveat: these can be notified multiple times, because the list gets updated by threads

我一直只想从 ImageList 获取最新的条目,所以我用 计数器 实现了它:

I always wanted to get only the newest entries from ImageList so I implemented it with a counter:

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)像这样使用这个方法:

The observers (Downloader here) use this method like this:

@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;
}

但是,有时循环会卡住并且似乎允许对该方法进行第二次调用.然后就是这样:

However, sometimes the loop gets stuck and a second call seems to be allowed on the method. Then this is what happens:

  • 下载器检索图像 70 到 70
  • 下载器检索图像 70 到 71
  • 下载器检索图像 70 到 72
  • 下载器检索图像 70 到 n

因此允许对该方法的第二次调用进入该方法,但计数器 readImageFrom 永远不会更新.

So a second call to the method is allowed entering the method, but the counter readImageFrom never gets updated.

当我删除对循环内其他函数的两个调用时,脚本开始工作.我知道它们没有同步,但是如果父"已经同步,它们是否必须同步?

When I remove both calls to the other functions within the loop, the script begins to work. I know they are not synchronized, but do they have to be if already the "parent" is synchronized?

filter.isOK() 是这样实现的(其他函数只返回 true 或 false;当我包含 hasRightColor 时代码失败,我猜是因为它是计算速度有点慢):

filter.isOK() is implemented like this (the other functions just return true or false; the code fails when I have hasRightColor included, I guess because it is a bit slower to calculate):

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

怎么会这样?Eclipse 没有显示任何抛出的异常(这当然会导致方法退出).

How can this happen? Eclipse does not show any thrown exception (which of course would cause the method to be exited).

也许还有一种完全不同的方法来仅从多个观察者那里获取列表的最新内容(每个观察者可能会多次通知,因为程序并行运行)?

Maybe there also is a totally different approach for getting only the newest content of a list from multiple observers (where each observer might be notified several times because the program runs parallel)?

推荐答案

好的,错误是一些邪恶的 NullPointerException 没有在 filter.isOk 中显示给我(谁知道为什么)().

Okay, the error was some wicked NullPointerException which was not displayed to me (whoever knows why) in filter.isOk().

我无法在我的 IDE 中看到它,因为我已经从 this.image 更改为参数传递 image,但忘记删除 private 在标题中,并更改三个函数中最后一个的参数.

I was not able to see it in my IDE, because I had changed from this.image to parameter-passing image, but forgot to remove private image in the header and to change the parameters of the last of the three functions.

所以 eclipse 既没有说明丢失的 image 也没有说明未使用的 this.image.

So eclipse did neither say anything about a missing image nor about an unused this.image.

终于.

这篇关于对函数的调用卡住了,但监视器似乎被释放了,怎么办?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆