开发者

Why aren't my threads start at the same time? Java

I have variable number of threads which are used for parallel downloading. I used this,

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

}

I don't know why but they wait for each other to complete. When using threads, I am supposed get mix开发者_如何学JAVAed print outs, since right then there are several threads running that code. However, when I print them out, they are always in order and one thread waits for the previous one to finish first. I only want them to join the main thread, not wait for each other. I noticed that when I measured time while downloading in parallel.

How can I fix this? Why are they doing it in order?

In my .java, there is MyThread class with run and there is Downloader class with static methods and variables. Would they be the cause of this? The static methods and variables?

How can I fix this problem?


you are creating a thread, waiting for it to complete (join), creating a new thread, waiting for it to complete (join) etcetera.

you should read the java documentation regarding threads to know what most method do: http://download.oracle.com/javase/tutorial/essential/concurrency/index.html and http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html


Easy. The problem is here:

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

Specifically, each iteration of the loop is creating a thread, starting it then waiting for it to join again. Which is why they're running in serial.

What you need to do is this:

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();
}

Which will go through the process of launching all the threads then it will loop through each thread and wait for it to exit.


You are much better off using an 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();


You start a thread and immediately join into it, thus rendering the whole threading useless, as you are waiting for the completion of the thread.

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

You should use a synchronized queue where the spawned threads themselves grab the parameters from, wait until the queue is empty and then proceed.


The join method waits for the chosen thread to die. The current thread (the one doing the loop that fires off the events) is waiting for the thread you just started to die before going around again and starting the next one.


Just do 2 loops, first start them all, then join them all.


For what I interpret from your question, since is not clearly stated, is that you have several downloader threads and want to synchronize them. In that case you need to use an external structure such as a CountdownLatch. A CountdownLatch is a "synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes." Think of it as a counter that decreases every time a downloader thread finishes, when the countdown reaches 0 then all threads should be done with their work.

Let's see some code taken directly from the official javadoc of CountdownLatch:

 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    

Your worker Runnable/Thread class would look something like this:

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

    downloadSomething();

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

I say is safe to assume since you will have to deal with InterruptedExceptions that can wake your thread while waiting, before all of them finish. For more information I recommend you take a look at the java.util.concurrent package. It's IMHO one of the best gems of Java and the documentation is thorough and often more than enough to understand the function of each structure.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜