同时创建动态数量的线程

15
每次我都需要创建数量不确定的线程变量。 我通过创建线程数组并创建多个线程来实现这一点。
但是,我不明白如何启动这些n个线程以表现出多线程的概念。 我希望它们能够并行运行。
如果有什么需要做的,请指导我在这种情况下做什么。
5个回答

38

但是,我不知道如何启动这些 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而不是自己管理线程。它们会为您完成所有这些操作,并且更易于管理。使用此方法的一个好处是将任务与运行它们的线程分开。例如,您可以启动10个线程并行运行1000s和1000s的任务。

以下是一些示例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线程执行器的教程获取更多信息。


1
如果我有1000个工作,它将创建1000个对象,这会导致性能问题吗? - Manoj Ramanan
1000个对象对于@ManojRamanan来说相当便宜。从对象带宽的角度来看,1000个字符串更昂贵。如果您创建了一百万个对象,您可能会注意到一些GC问题,因此我们通常会在队列上设置边界,以防Runnable生产者比消费者快得多。 - Gray
谢谢,@Gray提供的信息。你能分享更多的信息吗?我目前正在使用这个实现,你如何测试它? - Manoj Ramanan

3
尽量不要创建线程数组并尝试管理它们,否则很快就会变成一团糟。如果需要一个线程池来运行任务,则需要使用生产者-消费者队列。创建一个队列,并将其(或包含它作为成员的线程池对象实例)传递给创建的线程。线程循环执行,获取任务并执行它们。
最简单的方法是使用ExecutorService,如@Gray所述。
强调一遍,不要尝试在数组、列表或向量中微观管理线程,启动它们,在“老板/管理”循环中检查它们的状态,终止/中止它们,销毁它们等等。这就像保时捷911 - 花费大量的时间和金钱得到一辆车后,你会发现它似乎工作正常,然后突然坏掉并撞上树。
对于阻塞时间较长的作业,请使用专用线程;对于可以进行集中且快速完成的作业,请使用线程池。

2

基本伪代码:

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

1
如果我这样做,线程就不会并行运行。但是它们会像普通函数调用一样顺序运行。 - sowmya
@sowmya 我认为你需要学习一下线程。顺序调用一堆线程的start()方法并不意味着它们按顺序运行,只是意味着它们按顺序启动。 - Hunter McMillen
但是,他们按照我启动它们的顺序依次执行函数。据我所知,至少输出应该会改变。但是,这并没有发生。如果我错了,请纠正我。 - sowmya
它们各自执行其自己版本的函数。 - Hunter McMillen

2
在需要多线程的类中,我在类顶部设置了以下代码: private static final ExecutorService executor = Executors.newCachedThreadPool(); 在Java 8及以上版本中,我使用lambda表达式来在新线程中运行所需内容:
executor.submit(() -> {
        myOtherClass.myFunction(doSomething);
});

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


0
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");
    }

1
欢迎来到 Stack Overflow。虽然这段代码可能解决了提问者的问题,但请添加一些解释说明代码的作用以及为什么它能回答问题。 - Theo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接