同时创建动态线程数

Posted

技术标签:

【中文标题】同时创建动态线程数【英文标题】:Creating dynamic number of threads concurrently 【发布时间】:2012-04-22 22:48:08 【问题描述】:

每次我必须创建可变数量的线程。 我通过创建一个线程数组并创建多个线程来做到这一点。

但是,我不明白如何启动这 n 个线程,其行为类似于多线程概念。 我希望它们并行运行。

如果在这个场景中做什么,请指导。

【问题讨论】:

【参考方案1】:

但是,我不明白如何启动这 n 个线程,其行为类似于多线程概念。我希望它们并行运行。

您当然可以使用循环创建线程数组:

 Thread[] threads = new Thread[NUM_JOBS_TO_CREATE];
 for (int i = 0; i < threads.length; i++) 
     threads[i] = new Thread(new Runnable() 
         public void run() 
             // some code to run in parallel
             // this could also be another class that implements Runnable
         
     );
     threads[i].start();
 

这将导致线程在后台并行运行。然后,您可以稍后加入他们,等待他们全部完成后再继续。

// wait for the threads running in the background to finish
for (Thread thread : threads) 
    thread.join();

但我建议不要自己管理线程,而是使用内置的Java Executors。他们做这一切是因为你更容易管理。这种方法的好处之一是它将 tasks 与运行它们的 threads 分开。例如,您可以启动 10 个线程来并行运行 1000 个和 1000 个任务。

这里有一些示例 ExecutorService 代码:

 // create a pool of threads, 10 max jobs will execute in parallel
 ExecutorService threadPool = Executors.newFixedThreadPool(10);
 // submit jobs to be executing by the pool
 for (int i = 0; i < NUM_JOBS_TO_CREATE; i++) 
    threadPool.submit(new Runnable() 
         public void run() 
             // some code to run in parallel
             // this could also be another class that implements Runnable
         
     );
 
 // once you've submitted your last job to the service it should be shut down
 threadPool.shutdown();
 // wait for the threads to finish if necessary
 threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);

有关详细信息,请参阅Java tutorial on the thread executors。

【讨论】:

如果我有 1000 个作业,它将创建 1000 个对象,这会导致性能问题 1000 个对象非常便宜@ManojRamanan。从对象带宽的角度来看,1000 个字符串更昂贵。如果您创建了一百万个对象,您可能会注意到一些 GC 问题,因此我们通常在队列上设置边界,以防Runnable 生产者比消费者快得多。 感谢@Gray 提供的信息。您能否分享一些我目前正在使用此实现的信息。您如何测试它【参考方案2】:

尽量不要创建线程数组并尝试管理它们 - 它很快就会变成令人震惊的混乱。如果你需要一个线程池来运行任务,你需要一个生产者-消费者队列。创建一个并在创建线程时将其(或包含它作为成员的线程池对象实例)传递给线程。线程循环,获取任务并执行它们。

执行此操作的简单方法是使用@Gray (+1) 详述的 ExecutorService。

为了强调,我再说一遍,不要试图对数组、列表或向量中的线程进行微观管理、启动它们、在“老板/管理”循环中检查它们的状态、终止/中止它们、销毁它们等。等等。就像保时捷 911 - 在花费大量金钱/时间来获得一辆之后,你会得到一些似乎可以正常工作的东西,然后它会突然破碎并将你旋转成一棵树。

为长时间阻塞的作业使用专用线程,为那些可以集中快速完成的作业使用线程池。

【讨论】:

【参考方案3】:

基本伪代码:

create x threads, store them in an array or list;
for each thread in the list/array
   call start() on the thread object;

【讨论】:

如果我这样做,线程不会并行运行。但是,它们作为普通函数调用按顺序运行 @sowmya 我认为您需要阅读线程。在一堆线程上按顺序调用 start() 并不意味着它们是按顺序运行的,它只是意味着它们是按顺序启动的。 但是,它们是按照我启动它们的顺序依次执行的。据我所知,至少输出应该改变。但是,它没有发生。如果我错了,请纠正我。 它们各自执行各自版本的函数。【参考方案4】:

在一个需要多线程的类中我设置在类的顶部:

private static final ExecutorService executor = Executors.newCachedThreadPool();

& 在 Java 8+ 中,只要我需要在新线程中运行一些东西,就使用 lamda 表达式:

executor.submit(() -> 
        myOtherClass.myFunction(doSomething);
);

使用newCachedThreadPool,Java 将根据系统上的 cpu 核心数管理线程总数,并在一段时间不活动后自动停止它们(默认为60 秒)。

【讨论】:

【参考方案5】:
Scanner reader = new Scanner(System.in);
    System.out.println("Enter a positive number: ");
    int n = reader.nextInt();
    if(n>0)
        Thread[] ob = new Thread[n];
        for (int i = 0; i < ob.length; i++) 
            int num = i+1;
            ob[i] = new Thread(new Runnable() 
         public void run() 
             System.out.println("Hello, I am Thread #"+num);
         
            );
            ob[i].start();
        
    else
        System.out.println("Please Enter A Positive Integer");
    

【讨论】:

欢迎来到 Stack Overflow。虽然这很可能是解决 OP 问题的代码,但请对代码的作用以及它回答问题的原因添加一些解释。

以上是关于同时创建动态线程数的主要内容,如果未能解决你的问题,请参考以下文章

Java线程项目奇怪的行为,同时增加线程数

Java线程池

IOS多线程之NSOperation

CPU的核心数、线程数的关系和区别

CPU的核心数、线程数的关系和区别

CPU的“核心数”、“线程数”的关系和区别分别是啥?