关于java:如何创建用户定义的线程数?

How do you create a user-defined number of threads?

在我正在研究的程序中,我希望用户能够输入其处理器具有的处理线程数,以便该程序可以在用户计算机具有的线程数之间分配工作负载(它在进行常规计算) 。

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

这是我唯一想到的。我知道它是完全不正确的,并且您不能以这种方式命名线程,但是我是一名初学者(还在读高中),我只想添加一些东西来表明我正在尝试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
        }
    };
}

每个不确定我在说什么的人,我都在尝试创建计算机具有的线程数(即内核数),或者,如果使用的是英特尔的超线程技术,则创建两倍的内核数。您可能拥有的线程数量超出了系统一次执行的能力,但是我正在尝试做最有效的事情,将计算总数除以系统能够同时执行的线程数。我不知道如何让用户定义线程数,然后再创建该线程数(或让程序确定系统具有的线程数,然后再创建该数量)。


您可以像这样找出有多少处理器可用于JVM:

1
Runtime.getRuntime().availableProcessors()

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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]);
}

}


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

1
2
3
4
5
6
7
Executor e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// run a single task
e.execute(new Runnable() {
    public void run() {
        // do stuff here
    }
});

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


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

1
2
3
for(int i = 0; i < LARGE_NUMBER; i++) {
    f(i);
}

可以转换为并行版本:

1
2
3
4
5
6
7
8
9
10
11
class Task implements Runnable {
    private int i;

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

    public void run() {
       f(i);
    }
}

然后将初始for循环替换为:

1
2
3
4
5
6
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将负责使用相对于可用处理器而言足够数量的线程,并回收线程以使任务按需执行。


我喜欢用的是
ExecutorService执行程序= Executors.newFixedSizeThreadPool(int numberOfThreads);

然后让executor.execute(myRunnable)您的runnable :)
通过这种方法,您无需负责创建线程,并且可以确保您不会创建不必要的线程。

但是关于如何确定应该使用多少个线程,这取决于您的研究。


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

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

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


线程数与处理器无关。如果您使用的是单处理器,则您的程序将从一个线程跳转到另一个线程。

因此,您的方法中没有"不正确"的东西(当然,如果正确使用它)。