【问题标题】:Thread Jobs in JavaJava 中的线程作业
【发布时间】:2011-02-21 12:27:13
【问题描述】:

我想在 Java 中同时生成 200 个线程。我现在正在做的是进入一个循环并创建 200 个线程并启动它们。完成这 200 个线程后,我想再生成 200 个线程集,依此类推。

这里的要点是,我生成的前 200 个线程需要在生成下一组之前完成。我尝试了下面的代码,但它不起作用

for(int i=0;i<200;i++){
    Thread myThread = new Thread(runnableInstance);
    myThread.start();
}
for(int i=0;i<200;i++){
    Thread myThread = new Thread(runnableInstance);
    myThread.start();
}

注意:我有意将 for 循环放了两次,但我想要的效果并没有发生,因为第二个 for 循环是在第一组线程结束执行之前执行的。

请指教

【问题讨论】:

  • 我真的希望您将 200 用作“非常大的数字”的示例。我能想到的任务很少会使用 200 个相同的线程。
  • 小心,200 个线程已经接近在某些版本的 Linux 上可以生成的限制。您应该能够在 Windows 上生成更接近 2000 的值。 (通过反复试验找到这两个值)。当我对不同设备进行大量同步 SNMP 获取时,我必须这样做——CPU 可以轻松处理一千个未完成的请求。然而,一旦 NIO 出现,异步显然是一个更好的选择,并且可以扩展得更高。
  • @Bill K:Linux/Java 有哪些版本,为什么会这样?您是在谈论上世纪的 1.3 Java VM 吗? Linux 上的 AFAIK Java 多年来一直使用 NPTL,并且 Linux 已被证明能够在不到两秒的时间内扩展到 100 000 个 NTPL 线程。现在可能存在内核或 glibc 限制(如果我没记错的话,默认为 1024),但是用更高的值重新编译是微不足道的。除非你给出更详细的解释,否则我称之为 FUD。 java.sun.com/developer/technicalArticles/JavaTechandLinux/…
  • @Bill K:刚刚在我的 Linux 工作站上尝试过:默认情况下,无需更改任何参数,我可以启动近 4000 个 Java 线程。一个微不足道的重新编译,我会把那个数字放在 5 位数字中(哎呀,在我的普通工作站上甚至可能是 6 位)。所以,是的,我真的称之为“200 个线程相当接近你可以在某些版本的 Linux 上产生的限制” FUDdy 充其量。需要解释,因为您肯定不是在谈论那里的“常规”Linuxes/JVM。我很难考虑不支持超过 200 个 NPTL 的 Linux 版本。
  • @WizardOfOdds 好东西,谢谢。当我尝试这个时,它是在大约 199x 或 2000 年代初期的 Red Hat Linux 上,所以也许事情已经改变了。我撤销了我的警告 :) 然而值得注意的是,这是有限制的,它取决于操作系统和操作系统配置。此外,我倾向于考虑大约 1/2 的线程我可以启动“极限”,因为在那之后回收有时不够快,有时我因此无法创建新线程。所以windows实际上更接近4k,而linux更接近400......

标签: java multithreading


【解决方案1】:

您应该保留已创建线程的列表。然后,一旦您启动了所有这些,您就可以遍历列表并对每个列表执行join。当连接循环完成时,您的所有线程都将运行完成。

List<Thread> threads = new List<Thread>();
for(int i=0;i<200;i++){
    Thread myThread = new Thread(runnableInstance);
    myThread.start();
    threads.add(myThread);
}
//All threads are running
for(Thread t : threads) {
    t.join();
}
//All threads are done

【讨论】:

  • 轻微错字:for(Thread t : thread) 应该是 for(Thread t : threads)
【解决方案2】:

另一种解决方案是使用 Latch

final CountDownLatch latch = new CountDownLatch(200);

  for(int i=0; i<10; i++)
{

 Thread thread = new Thread()
{
    public void run()
{
     try{
         //do your work  

     }finally{
      latch.countDown();
     }
    }
   };

     }  
            //will block here util your threads all finished
  latch.await();

【讨论】:

  • 请点击edit链接并检查右栏信息的格式规则:)
【解决方案3】:

如果您使用的是 Java 1.5,请使用并发包,如果您使用的是 Java 1.4.2,则该包仍然可以作为反向端口使用,我很确定。

话虽如此,我最近有类似的任务要做;你可以很容易地通过使用ExecutorService 来实现它,你可以通过wait on the Future object to return 知道你的任务是否完成。非常干净的模式 - 也许不完全是您想要实现的目标,但在现实生活中它工作得非常好:-)。

一些代码:

BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
taskExecutor = new ThreadPoolExecutor(200, 200, 30, TimeUnit.SECONDS, workQueue);

futureList.add(taskExecutor.submit(new MyCallable()));

for (Future<Object> future : futureList) {
    future.get(); // wait for the task to complete
}

//... instantiate your second group of executors

【讨论】:

    【解决方案4】:

    某种伪代码,你需要实例化可调用的;-)

    while( moreThreads ) {
        List<Callable<Integer>> threads = new ArrayList<Callable<Integer>>();
        for( int i = 0; i < 200; ++i ) {
            threads.add(new Callable<Integer>() );
        }
    
        FixedThreadPool pool = Executers.newFixedThreadPool(200);
        pool.invokeAll(threads);
        pool.shutdown();
    }
    

    【讨论】:

      【解决方案5】:

      感觉是功课,但是...

      spawnAndWait() {
       Thread T[] = new Thread[n];
       for(int i=0;i<n;i++){
           T[i] = new Thread(runnableInstance);
           T[i].start();
       }
       for (Thread t : T) {
        t.join();
       }
      }
      

      【讨论】:

        【解决方案6】:

        您需要使用join() 等待线程完成:

        // run first set of threads
        List<Thread> threads = threadsList; // save reference to all threads
        for(Thread t : threads){
            t.join();
        }
        // all threads finished
        
        // run other set of threads
        

        【讨论】:

        • 我没有反对,但你在循环中的加入意味着它会等待每个线程完成,然后再开始下一个......你已经序列化了这 200 个线程。
        • 启动后需要加入。
        • CPerkins - 不正确,这个 sn-p 只是在线程和 join()s 上迭代。无论如何@unholysampler 有更好的 sn-p。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-12
        • 1970-01-01
        • 2020-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多