如何创建用户定义的线程数?

Posted

技术标签:

【中文标题】如何创建用户定义的线程数?【英文标题】:How do you create a user-defined number of threads? 【发布时间】:2012-01-08 18:30:35 【问题描述】:

在我正在处理的程序中,我希望用户能够输入他们的处理器拥有的处理线程数,以便程序可以在线程数之间分配工作负载(它正在进行一般计算)用户的电脑有。

或者,有没有一种方法可以让程序检测系统配置以获取线程数而无需询问用户?这会更好,但我不知道是否有办法做到这一点。

这是我唯一能想到的。我知道这是完全不正确的,你不能这样命名一个线程,但我是一个初学者(还在上高中),我只是想包括一些东西来表明我正在尝试。

for(int i = 0; i < threads; i++) 

    Thread thread(i) = new Thread()
        public void run() 
            double endNum = 0;

            for(double numberRun = 0; numberRun <= calcs/threads; numberRun++)
                endNum += (num * 999999999);
            

            System.out.println("Thread " + i + " complete! The numerical result of the calculation is " + endNum);
        
    ;

每个不确定我在说什么的人,我正在尝试创建计算机拥有的线程数,也就是内核数,或者,如果它使用的是英特尔的超线程,那么内核数是两倍。您可以拥有比系统一次能够执行的线程更多的线程,但我正在尝试做最有效的事情,并将计算总数划分为系统能够同时执行的线程数。我不知道如何让用户定义线程数然后创建该线程数(或者让程序确定系统拥有的线程数然后创建该数)。

【问题讨论】:

你检查了吗:***.com/questions/1980832/… 除非您也将它们固定到核心/HT 上,否则这是没有意义的,但即便如此,您也应该知道,在现代多任务操作系统中,您的线程不会是孤立的,因此在大多数情况下,您让操作系统的调度程序决定运行什么以及何时运行要好得多。它会做得很好,而您无法知道系统中的其他线程在做什么,并且如果您能够将一个线程固定到一个忙于其他事情的核心,则可能会面临性能下降的风险。 @Fredrik - 对于 CPU 密集型任务(假设这是机器上唯一或最普遍的任务),您通常不希望运行比 CPU 更多的线程,否则您'只是在制造争用。但是您也不想减少 CPU 的数量,因为您不会使用所有 CPU。 nCPUIntensiveThreads == nProcessors 实际上是一个相当公平的目标。 @james 你是对的,你可能不想要比内核更多的线程(除非替代方案是在之后直接运行额外的工作),但以相同数量为目标可能证明同样糟糕除非您独自在系统上或可以控制调度程序。除非您非常清楚您的线程所依赖的内容,否则饿死其他线程很容易损害您在托管环境中的整体性能。对于新手来说,这样的优化很可能会损害性能。 我建议使用以 nuber of cores -1 作为池大小的执行器服务。 【参考方案1】:

您可以像这样了解 JVM 有多少个处理器可用:

Runtime.getRuntime().availableProcessors()

用于拆分纯数值计算的最佳线程数可能是每个处理器一个。如果这些线程中的任何一个不得不偶尔阻塞 IO,那可能会更多。

【讨论】:

但是如何创建用户计算机拥有的线程数呢?这意味着能够在许多不同的系统配置上运行,并且程序应该自动创建正确数量的线程。 @user11373731 - 我认为您在 cmets 中混合了线程和处理器这两个词。上面发布的命令告诉您可用的处理器数量 - 通常也是您想要的线程数。 @James - 我知道处理器的数量也是您想要的线程数,但我不知道如何让程序在确定如何执行该线程数后执行计算许多可以根据该代码 sn-p 的结果使用。 @user:看看下面詹姆斯的回答。 @user1137371 - 如果您询问如何运行它,请参见下文。如果您询问如何将计算分解为单独的任务,则必须提供有关您正在计算的内容的更多信息,因为它是相当特定于任务的(因此是困难的部分!)【参考方案2】:
class Task implements Runnable 
  Task(/** Whatever you need to identify the subset of tasks to run goes here*/) 

  

  public void run() 
    // do the calcs
  


int nProcs = Runtime.getRuntime().getAvailableProcessors();

Task[] tasks = new Task[nProcs];
for (int i = 0; i < nProcs; i++) 
   tasks[i] = new Task(/** Whatever parameters for this batch*/);
   new Thread(tasks[i]).start(); 
   // Alternatively, use Executors.newFixedThreadPool() to get a service above, and submit the runnable there, getting a future for the result, something like this:
   Future f = executor.submit(task[i]);

【讨论】:

James,我可以给你发电子邮件吗?我有几个问题和一些代码,在这里讨论起来有些困难。如果你有时间,请发邮件给我 numa.robertson@gmail.com【参考方案3】:

如果您要执行一堆不同的不同任务,而不是尝试将一个大任务拆分为多个并行运行的小任务,您可能需要使用Executor:

Executor e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// run a single task
e.execute(new Runnable() 
    public void run() 
        // do stuff here
    
);

正如其他人指出的那样,线程池的最佳大小取决于各种因素,例如任务执行的 IO 量,但可用内核的数量应该是一个合理的默认值。

【讨论】:

我正在尝试在所有可用的处理线程之间拆分一项大任务(重复做一个方程式)。 @user1137371 那么直接使用线程还是使用执行器并不重要,虽然我还是喜欢后者,因为Futures。在 Runnable 的主体中,您可以使用问题中的方法主体,threads 的值将是 Runtime.getRuntime().availableProcessors()(或您认为合适的任何值。)【参考方案4】:

我喜欢使用的是 ExecutorService executor = Executors.newFixedSizeThreadPool(int numberOfThreads);

然后让 executor.execute(myRunnable) 你的 runnables :) 在这种方法中,您不负责创建线程,并且您可以保证不会创建不必要的线程。

但至于如何确定应该使用多少线程,则由您自己研究。

【讨论】:

【参考方案5】:

在我看来,您正在寻找的也是任务到线程的映射策略。比如这样的循环:

for(int i = 0; i < LARGE_NUMBER; i++) 
    f(i);

可以转换为并行版本:

class Task implements Runnable 
    private int i;

    public Task(int i) 
       this.i = i;
           

    public void run() 
       f(i);
    

然后将最初的 for 循环替换为:

ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < LARGE_NUMBER; i++) 
    exec.submit(new Task(i));


exec.awaitTermination(1000, TimeUnit.HOURS); // wait for all tasks to finish

ExecutorService 将负责使用与可用处理器相关的足够线程数,并回收线程以便按需执行任务。

【讨论】:

【参考方案6】:

线程数不取决于处理器。如果您使用的是单处理器,那么您的程序将从一个线程跳转到另一个线程。

所以,你的方法没有任何“不正确”的地方(当然,如果你能正确使用它的话)。

【讨论】:

线程的最佳数量当然 - 确实 - 取决于处理器的数量,如果你想要一些 CPU 限制和性能关键的东西。【参考方案7】:

我想您是在问系统可以拥有的最大线程数??

正如here 所讨论的,系统可以拥有的线程数没有最大限制(因为Java 程序在Java 虚拟机中运行,您将拥有的限制是Java 虚拟机- JVM 的限制)。限制是您可以分配给线程的资源量。

如果您询问当前正在运行多少线程(可能已由任何外部程序或 JVM 内部启动),那么您可能会发现,但我认为它没有任何用处对于您的情况,因为您启动的线程与系统中运行的其他线程没有任何关系!

【讨论】:

在实践中,您几乎可以肯定地分配比您可以合理使用的更多的线程。在超过几千之后,您开始花费相当多的 CPU 来在它们之间切换。

以上是关于如何创建用户定义的线程数?的主要内容,如果未能解决你的问题,请参考以下文章

是否有人创建了将十进制数作为参数的雪花用户定义函数 (SQL)?

dubbo无法创建线程问题

临时表是线程安全的吗?

记录一次并发测试的bug

Jmeter线程组创建及定义

oracle 如何限定用户并发会话数