简体   繁体   English

为什么我的线程不能同时启动? Java的

[英]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 mixed 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. 在我的.java中,有一个带有run的MyThread类,还有一个带有静态方法和变量的Downloader类。 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 你应该阅读有关线程的java文档,了解大多数方法的作用: http//download.oracle.com/javase/tutorial/essential/concurrency/index.htmlhttp://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 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. join方法等待所选线程死亡。 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. 当前线程(执行触发事件的循环的线程)正在等待刚刚开始死亡的线程,然后再次开始并开始下一个线程。

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

只做2个循环,首先启动它们,然后将它们全部加入。

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 . 在这种情况下,您需要使用外部结构,例如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." CountdownLatch是一种“同步辅助工具,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。” 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. 可以把它想象成一个计数器,每次下载器线程完成时减少,当倒计时达到0时,所有线程都应该完成他们的工作。

Let's see some code taken directly from the official javadoc of CountdownLatch: 让我们看一下代码直接来自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    

Your worker Runnable/Thread class would look something like this: 你的worker Runnable / Thread类看起来像这样:

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. 我说可以安全地假设,因为你必须处理InterruptedExceptions,它们可以在等待之前唤醒你的线程,然后才能完成。 For more information I recommend you take a look at the java.util.concurrent package. 有关更多信息,我建议您查看java.util.concurrent包。 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. 它是恕我直言最好的Java之一,文档是彻底的,通常足以理解每个结构的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM