1

我有以下情况:

  • 大约 10 个线程在网络上抓取图像
  • 所有找到的图像必须以某种方式返回到其他 10 个线程(用于分析)

如前所述,我想与其他 10个线程同时处理图像

目前我有一个自己的列表的单例实现:

public class ImageList extends Observable implements Iterable<Image> {
    private final BlockingQueue<Image> images = new LinkedBlockingQueue<Image>();

    private static class InstanceHolder {
        public static ImageList instance = new ImageList();
    }

    public static ImageList getInstance() {
        return InstanceHolder.instance;
    }

    private ImageList() {

    }

    public synchronized void execute(Image job) throws InterruptedException {
        images.put(job);

        new Thread(job).start();

        System.out.println("notify observers");
        this.setChanged();
        this.notifyObservers();

        System.out.println(this.countObservers());
    }

    @Override
    public Iterator<Image> iterator() {
        return images.iterator();
    }
}

一旦找到图像,我就会执行ImageList.execute(image),但我不喜欢这个解决方案,因为并行进程没有上限(它可能会变成数千个)。

我的另一个想法:

  • 附加列表 imagesFound传递给我所有的爬虫,让他们将所有图像添加到该列表中
  • 在 Main 类中启动 5 个线程,不断检查imagesFound并处理新元素

但是,我也不喜欢这个解决方案,因为传递一个线程并不真正需要的数组(但只是用来传回找到的数据)对我来说似乎是错误的。如果我想在一个网站上搜索 20 个不同的信息,它可能会变成 20 个不同的列表。

那么,您通常如何实现从线程返回数据(在我的情况下:特别是如果该数据本身应由其他线程处理)。

4

1 回答 1

4

也许是一个线程池?查看ExecutorService

  • 您可以设置工作线程的数量。
  • 它自动封装了一个线程安全的工作队列。

例子:

class Task implements Callable<Object> {

    private Image job;

    public Task(Image job) {
       this.job = job;
    }

    public Object call() {
        // crawl
        return result;
    }
}

...

// Initialize thread pool
ExecutorService exec = Executors.newFixedThreadPool(10);

// every time you get a new job
Future<Object> result = exec.submit(new Task(job));

// when you want to collect the result
Object obj = result.get();
于 2012-07-13T16:34:27.587 回答