2012-02-25 7 views
1

私のマルチスレッド化の経験は限られているので、正直言ってこれはひどい考えです。 マルチスレッディングリストの正確さ

50件のURL(例) コールジェネリックメソッドは、URLを処理するために、リスト内のURLの範囲にアクセスするためのスレッド(例えば5)の 使用x量のArrayListを(HTMLを取得):ここで私が何をしたいです結果を他のスレッドの結果と一緒にマスターリストに保存する

現在、私は複数のスレッドでArrayListを処理しています。私の現在の考えは、リスト内のURLの数でリストを分割し、例えば処理する各スレッドに

スレッド1 - 0-7 スレッド2 - 8-15

など

私はこれはひどい方法であると仮定していますが、私は本当に例のアプローチを見つけることができません。

ヘルプ/アドバイスをいただければ幸いです。

+0

は、同時に複数のhtmlページをダウンロードするためにここで見てみたいことがありますが、それの最終目標である – Ash

+0

ダウンロード[Javaの同時アニメーション](http://sourceforge.net/projects/javaconcurrenta/)、与えるべきですあなたは物事をどのように動かすことができるか考えています。 –

答えて

4
  1. 各スレッドが単一のURLを処理するスレッドのプールを、 のリストから作成します。
  2. スレッドが完了すると、一覧から次のURLを取得して処理できるようにグローバルインデックスカウンタを保持します。
  3. すべてのURLが処理されるまでこれを実行します。 index == list.size()

このように、すべてのスレッドは、ジョブが完了するまで完全に利用されます。プール内のスレッド数で遊んで、特定のランタイム環境のパフォーマンスを最適化することができます。

インデックスカウンタのコードがスレッドセーフであることを確認してください。私は代替/批判に開いている

+1

カウンタではなくラッチを使用すると、メインスレッドはラッチを待つことができます... – Nim

+0

そして、スレッド自体で、まったく同じ時刻にスレッド自体を変更しないようにしてください。同期化された関数、または既存のConcurrentデータ構造などを使用してください。 – EdH

1

... :)私は、マルチスレッドの専門家ではないが、過去に、私はこのような何かやった:

public class MainController { 

    public static void main(String[] args) { 
     ThreadGroup workers = new ThreadGroup("workers"); 
     Iterator<String> urls = getUrlList().iterator(); 
     while(workers.activeCount() < 5 && urls.hasNext()) { 
      UrlProcessor proc = new UrlProcessor(urls.next()); 
      Thread worker = new Thread(workers, proc); 
      worker.start(); 
     } 
    } 

    private static List<String> getUrlList() { 
     return null; //To change body of created methods use File | Settings | File Templates. 
    } 
} 


public class UrlProcessor implements Runnable { 

    private String url; 

    public UrlProcessor(String url) { 
     this.url = url; 
    } 

    public void run() { 
     // process URL 
    } 
} 
2

はるかに簡単なアプローチはしているがジャストオンデマンドURLを処理し、その後、Future Sを使用して結果を取得するためにExecutorServiceを使用します。

class URLProcessor { 

    class ThreadTask implements Callable<String> { 
     private String url; 

     public ThreadTask(String url) { 
      this.url = url; 
     } 

     public String call() { 
      // process url 
      // return a String result 
     } 
    } 

... 


// input urls 
List<String> urls = new ArrayList<String>(); 
// futures to retrieve task results 
List<Future<String>> futures = new ArrayList<Future<String>>(); 
// results 
List<String> results = new ArrayList<String>(); 
// pool with 5 threads 
ExecutorService exec = Executors.newFixedThreadPool(5); 

// enqueue tasks 
for(String url: urls) { 
    futures.add(exec.submit(new ThreadTask(url))); 
} 

// wait for tasks to finish 
for(Future<String> future: futures) { 
    results.add(future.get()); 
} 
+0

この例をお寄せいただきありがとうございます。私はあなたに借りています:) – Ash

+0

@Ash:あなたの問題は解決していませんか?このアプローチで他の問題を見つけましたか? – Tudor

1

は、各URLのためのタスクを作成し、エグゼキュータに提出。

タスクは、次のようになります。

class UrlTask implements Callable<String>{ 
    final URL url; 

    UrlTask(URL url){ 
     this.url = url; 
    } 

    public String call(){ 
     return fetch(url); 
    } 
} 

と、このように使用する:

Collection<Future<String>> results = new Arraylist<Future<String>>(); 
for(URL each : urls){ 
    UrlTask task = new UrlTask(each); 
    Future<String> result = executor.submit(task); 
    results.add(result); 
} 

for(Future<String> result : results){ 
    String content = result.get(); 
    // process content 
} 
1

スレッドプールは、スレッドのライフサイクルのオーバーヘッドの問題と問題の両方の解決策を提供していますリソーススラッシングの

あなたはThread pools and work queues