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 に答える