2011-09-21 12 views
12

スレッドを使用してパターンに一致する複数のファイルをダウンロードしようとしています。パターンは1または5または10の差分サイズのファイルと一致する可能性があります。javaスレッドを使用して複数のファイルをダウンロード

簡単に言うと、ファイルをダウンロードする実際のコードはdownloadFile()メソッドにあり、fileNamesはパターンに一致するファイル名のリストです。どのようにスレッドを使ってこれを行うのですか?各スレッドは1つのファイルしかダウンロードしません。 forループ内に新しいスレッドを作成することをお勧めします。

for (String name : fileNames){ 
    downloadFile(name, toPath); 
} 

答えて

31

、それは、おそらくよりパフォーマンスよりクリーンだとあなたを可能にしますが(スレッド数、スレッド名など)の上に、後に、より簡単に物事を変更するには:

ExecutorService pool = Executors.newFixedThreadPool(10); 
for (String name : fileNames) { 
    pool.submit(new DownloadTask(name, toPath)); 
} 
pool.shutdown(); 
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
// all tasks have now finished (unless an exception is thrown above) 

そしてどこか他のあなたのクラスでは、実際の仕事の馬を定義DownloadTask:それは「以前に提出したタスクが終了する前に実行できるようになります」ので

private static class DownloadTask implements Runnable { 

    private String name; 
    private final String toPath; 

    public DownloadTask(String name, String toPath) { 
     this.name = name; 
     this.toPath = toPath; 
    } 

    @Override 
    public void run() { 
     // surround with try-catch if downloadFile() throws something 
     downloadFile(name, toPath); 
    } 
} 

shutdown()方法は、非常に紛らわしい名称を持っています。 awaitTermination()は処理する必要があるInterruptedExceptionと宣言します。

+0

これは 'DownloadTask'(私の推薦)の中で' downloadFile() 'メソッドを定義するか、外部で' static'宣言する必要があります。 –

+0

'@Philipp Reichart'シャットダウン後に新しいダウンロードタスクがプールに受け入れられません。もし私があなただったら、これを避けるでしょう。 – Bitmap

+0

この場合、プールがシャットダウンされた後にプールに新しいタスクが追加されないため、これは問題にはなりません。最初のコードスニペットはメソッド内に存在するはずであり、すべての呼び出しで新しいプールを作成します。 –

1

はい、スレッドインラインを作成できます。

for (final String name : fileNames){ 
    new Thread() { 
     public void run() { 
      downloadFile(name, toPath); 
     } 
    }.start(); 
} 
5

はい、確かにfor-loop内に新しいスレッドを作成できます。このような何か:またExecutors.newFixedThreadPool(int)によって作成されたスレッド・プールには、例えば、Executorを使用することを検討すべきである

List<Thread> threads = new ArrayList<Thread>(); 
for (String name : fileNames) { 
    Thread t = new Thread() { 
    @Override public void run() { downloadFile(name, toPath); } 
    }; 
    t.start(); 
    threads.add(t); 
} 
for (Thread t : threads) { 
    t.join(); 
} 
// Now all files are downloaded. 

+0

一度に3つのファイルをダウンロードするには、どうすれば同時ダウンロード数を制限できますか。 Executor – user373201

+0

@ user373201の使用例があります:私が 'Executors.newFixedThreadPool(int)'に提供したリンクに従って@Phillip Reichartの答えを見直してください。 – maerics

1

Executorを使用してください。これを試してください。

ExecutorService exec= Executors.newCachedThreadPool() 
for (String name : fileNames){ 
exec.submit(new Runnable() 
{ 
    public void run() 
    { 
    downloadFile(name, toPath); 
    } 
}); 
} 

あなたが使用することができ、同時に実行されている3件のダウンロード、言いたい場合は:あなたは本当にExecutorServiceの代わりに、個々のスレッドを使用したい

Executors.newFixedThreadPool(3) 
+0

これは、 'Runnable'を' execute()している間に 'exec.submit()'を呼び出すことをブロックしています: –

+0

@Philipp Reichartあなたが話していることを本当に知っていますか?実行中に何ブロック?ブルブルを聞く!あなたが何を知っているのか分からないときには、人に印を付けるのを避けてください。 – Bitmap

+0

はい、私は実際にこれで一度噛まれました。 ['Execute.execute()'](http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executor.html#execute(java.lang.Runnable))は、 "... Executor実装の裁量により、新しいスレッド、プールされたスレッド、**を呼び出しスレッド**で実行します。"実際に変数をExecutorServiceとして宣言し、[submit()'](http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html# (実行可能なjava.lang.Runnable))。 –

0

上記のアプローチはすべてスレッドを作成しますが、実際のConcurrenyは達成されません。

ExecutorService pool = Executors.newFixedThreadPool(5); 
final File folder = new File("YOUR_FILES_PATH"); 
int l = folder.listFiles().length; 
System.out.println("Total Files----"+folder.listFiles().length); 
long timeStartFuture = Calendar.getInstance().getTimeInMillis(); 
    pool.execute(new DownloadFile(folder,0,l/2)); 
    pool.execute(new DownloadFile(folder,(l/2),l)); 
    pool.shutdown(); 
    try { 
     pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    long timeEndFuture = Calendar.getInstance().getTimeInMillis(); 
    long timeNeededFuture = timeEndFuture - timeStartFuture; 
    System.out.println("Parallel calculated in " + timeNeededFuture + " ms"); 

上記のプログラムは、並行性を達成し、あなたの要件ごとに変更してくださいするために使用されます。

関連する問題