2010-12-27 12 views
2

私は並列ダウンロードに使用されるスレッドの数が可変です。私はなぜ知らないが、彼らが完了するまでにお互いを待つスレッドが同時に起動しないのはなぜですか? Java

for(int i = 0; i< sth; i++){ 
     thrList.add(new myThread (parameters)); 
     thrList.get(i).start(); 
     thrList.get(i).join(); 

}

、これを使用していました。スレッドを使用しているときは、すぐにそのコードを実行するスレッドがいくつかあるので、私は混在したプリントアウトを取得することになっています。しかし、私がそれらをプリントアウトすると、それらは常に順番になり、1つのスレッドは前のものが最初に終了するのを待ちます。私は、彼らがお互いを待つのではなく、メインスレッドに参加したいだけです。私は並行してダウンロード中に時間を測定したときに気づいた。

どうすればこの問題を解決できますか?なぜ彼らはそれを順番にやっているのですか?

私の.javaには、 があります。実行中のMyThreadクラスがあり、静的メソッドと変数を持つDownloaderクラスがあります。彼らはこれの原因だろうか?静的メソッドと変数

この問題を解決するにはどうすればよいですか?

答えて

1

あなたはちょうどそれらすべてに参加し、その後、それらのすべてを最初に起動し、2つのループを行うExecutorServiceの

ExecutorService es = Executors.newCachedThreadPool(); 
// pool is reusable 

List<Callable<Void>> callables = new ArrayList<Callable<Void>>(); 
for(int i=0;i<sth;i++) callables.add(new MyCallable(i)); 
for(Future<Void> futures : es.invokeAll(callables)) 
    futures.get(); 
+0

これはお互いの権利を待つことはありませんか?私の場合でも、join()ループを分離した後でさえも同じことが起こります。 – Ada

+0

MyRunnableとパラメータiの関係を知りません。それは私のmyThreadですか? – Ada

+0

"ExecutorServiceの型のメソッドinvokeAll(Collection <?extends Callable >)は引数には適用されません(リスト)" – Ada

11

スレッドを作成して、完了(ジョイン)、新しいスレッドの作成、完了(ジョイン)などの待機を待っています。

あなたは、ほとんどの方法は何をすべきか知っているスレッドに関するJavaドキュメントを読んでください: http://download.oracle.com/javase/tutorial/essential/concurrency/index.html

+0

ohw私はそれを持っています。どうすれば修正できますか? – Ada

+1

@Ada: 'join()'の呼び出しを取り除きます – sjngm

+0

私は参加したループのために別のものを作っていましたが、変更はありませんでした。それでも、parellelではなく、連続してダウンロードされます。 – Ada

1

http://download.oracle.com/javase/6/docs/api/java/lang/Thread.htmlあなたが待っていると、無駄な全スレッドをレンダリング、それに参加し、すぐにスレッドを開始し、スレッドの完了。

thrList.get(i).start(); 
    thrList.get(i).join(); 

スポーンされたスレッド自体がパラメータを取得し、キューが空になるまで待ってから続行する同期キューを使用する必要があります。

2

簡単。問題は次のとおりです。

具体的には、ループを繰り返すたびにスレッドが作成され、スレッドが再び参加するのを待っています。これが彼らが連続して走っている理由です。すべてのスレッドを起動するプロセスを通過します

for(int i = 0; i< sth; i++){ 
     thrList.add(new myThread (parameters)); 
     thrList.get(i).start(); 
} 

for(int i = 0; i< sth; i++){ 
     thrList.get(i).join(); 
} 

それがする各スレッドをループし、それが終了するのを待ち:

は何をする必要があると、このです。

+0

彼らはまだお互いを待っている理由がわからない – Ada

+0

@adaそれはもちろんスレッドが何をしているのかによって異なります。スレッドがブロッキングリソースにアクセスしている場合(1つは待ってからアクセスする必要があります)、これは問題になる可能性があります。私はもっ​​と見ることなく知らない。他の人はドキュメントや、もっと綺麗に見えるExecutorサービスを指摘しています。私のものは単に素早く汚れた方法です。 –

+0

また、こんにちはdownvoter、これに正確に何が間違っているかについてコメントしてください?私は何も問題ないと思うし、睡眠とsystem.outsを含む私のデモは並行してうまく動作します。 –

1

joinメソッドは、選択されたスレッドが終了するのを待ちます。現在のスレッド(イベントを発生させるループを実行しているスレッド)は、直前にスレッドを終了し、次のスレッドを開始する前にスレッドを待機しています。

+0

申し訳ありませんが、System.getCurrentThread()。join()を取得しませんでした。子スレッドが終了してメインスレッドに参加するようになりますか? – Ada

+0

私はそれを使用しましたが、参加しませんでした。メインスレッドだけが必要なときは、アクティブなスレッドの数を表示していましたが、それは5でした。どのように私はそれらに参加できますか? – Ada

+0

申し訳ありませんが、間違いをしました。 System.getCurrentThread()。join()を呼び出すのではなく、メインスレッドへの参照が必要です。それはあなたがとにかく期待していることをしません。 ExecutorService(http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html)を使用すると、簡単に実行できます。 –

0

を使用してオフにはるかに優れています。

0

あなたの質問から私が解釈するものは、明確に述べられていないので、いくつかのダウンローダスレッドがあり、それらを同期したいということです。その場合は、CountdownLatchのような外部構造を使用する必要があります。CountdownLatchは、「他のスレッドで実行されている一連の操作が完了するまで、1つまたは複数のスレッドを待機させる同期補助機能」です。ダウンローダスレッドが終了するたびにカウントダウンが0に達すると、すべてのスレッドが作業を完了する必要があるたびに減少するカウンタと考えることができます。

のは、たCountDownLatchの公式のjavadocから直接取得いくつかのコードを見てみましょう:

CountDownLatch startSignal = new CountDownLatch(1); 
CountDownLatch doneSignal = new CountDownLatch(N); 

for (int i = 0; i < N; ++i) // create and start threads 
    new Thread(new Worker(startSignal, doneSignal)).start(); 

startSignal.countDown(); // Threads are waiting for startSignal's counter to reach 0 and start their work, more or less at the same time 
doneSignal.await(); // The current thread will sleep at this point until all worker threads have each one called doneSignal.countDown() and the countdown reaches 0 

joinDownloadedPieces(); // At this point is safe to assume that your threads have finished and you can go on with anything else  

あなたの労働者のRunnable/Threadクラスは、このようなものになります。

public void run() { 
    startSignal.await(); // Wait until given the go 

    downloadSomething(); 

    doneSignal.countDown(); // Notify that we are done here 
} 

を私は以来と仮定しても安全であると言いますInterruptedExceptionsを処理する必要があります。InterruptedExceptionsは、待機中にスレッドをスリープ状態にすることができます。詳細については、java.util.concurrentパッケージをご覧ください。それはJavaの最高の宝石の一つであり、ドキュメンテーションは徹底しており、多くの場合、各構造の機能を理解するのに十分です。

+0

私は分かりませんが、これはパラレルダウンロードと同じくらい単純なことのために過度のもののようです。その後、 'ExecutorService'を再度使用することは、長時間実行するアプリケーションの多くのスレッドを作成して破棄することを無効にすることをお勧めします。 –

+0

@Neil私は同意します。エグゼクティブはスレッドを直接使用するよりも優先されるべきです。しかし、ラッチはスレッドの同期に使用され、ライフサイクルを管理するのではありません。 – teto

+0

はい、スレッドの開始点を同期させるためのOPからの要件はないようです。つまり、各スレッドは準備ができたらすぐに開始できます。したがって、これを1つのラッチに減らすことができます。 –

関連する問題