Java 如何根据 CPU 内核扩展线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1980832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to scale threads according to CPU cores?
提问by Andreas Hornig
I want to solve a mathematical problem with multiple threads in Java. my math problem can be separated into work units, that I want to have solved in several threads.
我想用 Java 中的多线程解决数学问题。我的数学问题可以分成多个工作单元,我想在多个线程中解决这些问题。
I don't want to have a fixed amount of threads working on it, but instead an amount of threads matching the amount of CPU cores. My problem is, that I couldn't find an easy tutorial in the internet for this. All I found are examples with fixed threads.
我不想让固定数量的线程在其上工作,而是要使用与 CPU 内核数量相匹配的线程数量。我的问题是,我在互联网上找不到简单的教程。我发现的都是固定线程的例子。
How can this be done? Can you provide examples?
如何才能做到这一点?你能提供例子吗?
采纳答案by JasCav
You can determine the number of processes available to the Java Virtual Machine by using the static Runtime method, availableProcessors. Once you have determined the number of processors available, create that number of threads and split up your work accordingly.
您可以通过使用静态运行时方法,确定提供给Java虚拟机的进程数availableProcessors。确定可用处理器的数量后,创建该数量的线程并相应地拆分您的工作。
Update: To further clarify, a Thread is just an Object in Java, so you can create it just like you would create any other object. So, let's say that you call the above method and find that it returns 2 processors. Awesome. Now, you can create a loop that generates a new Thread, and splits the work off for that thread, and fires off the thread. Here's some psuedocode to demonstrate what I mean:
更新:为了进一步澄清,线程只是 Java 中的一个对象,因此您可以像创建任何其他对象一样创建它。因此,假设您调用上述方法并发现它返回 2 个处理器。惊人的。现在,您可以创建一个循环来生成一个新线程,并为该线程拆分工作,并触发该线程。这是一些伪代码来演示我的意思:
int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
Thread yourThread = new AThreadYouCreated();
// You may need to pass in parameters depending on what work you are doing and how you setup your thread.
yourThread.start();
}
For more information on creating your own thread, head to this tutorial. Also, you may want to look at Thread Poolingfor the creation of the threads.
回答by Eric Petroelje
On the Runtime class, there is a method called availableProcessors(). You can use that to figure out how many CPUs you have. Since your program is CPU bound, you would probably want to have (at most) one thread per available CPU.
在 Runtime 类中,有一个名为 availableProcessors() 的方法。你可以用它来计算你有多少 CPU。由于您的程序受 CPU 限制,您可能希望(至多)每个可用 CPU 有一个线程。
回答by DaveC
You probably want to look at the java.util.concurrent framework for this stuff too. Something like:
您可能也想查看有关这些内容的 java.util.concurrent 框架。就像是:
ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
public void run() {
// do one task
}
});
or
或者
Future<String> future = pool.submit(new Callable<String>() {
public String call() throws Exception {
return null;
}
});
future.get(); // Will block till result available
This is a lot nicer than coping with your own thread pools etc.
这比处理自己的线程池等要好得多。
回答by David Soroko
Doug Lea (author of the concurrent package) has this paper which may be relevant: http://gee.cs.oswego.edu/dl/papers/fj.pdf
Doug Lea(并发包的作者)有这篇可能相关的论文:http: //gee.cs.oswego.edu/dl/papers/fj.pdf
The Fork Join framework has been added to Java SE 7. Below are few more references:
Fork Join 框架已添加到 Java SE 7。以下是更多参考资料:
http://www.ibm.com/developerworks/java/library/j-jtp11137/index.htmlArticle by Brian Goetz
http://www.ibm.com/developerworks/java/library/j-jtp11137/index.htmlBrian Goetz 的文章
http://www.oracle.com/technetwork/articles/java/fork-join-422606.html
http://www.oracle.com/technetwork/articles/java/fork-join-422606.html
回答by fl0w
The standard way is the Runtime.getRuntime().availableProcessors() method. On most standard CPUs you will have returned the optimal thread count (which is not the actual CPU core count) here. Therefore this is what you are looking for.
标准方法是 Runtime.getRuntime().availableProcessors() 方法。在大多数标准 CPU 上,您将在此处返回最佳线程数(这不是实际的 CPU 核心数)。因此,这就是您要寻找的。
Example:
例子:
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Do NOT forget to shut down the executor service like this (or your program won't exit):
不要忘记像这样关闭执行程序服务(否则您的程序将不会退出):
service.shutdown();
Here just a quick outline how to set up a future based MT code (offtopic, for illustration):
这里只是一个快速概述如何设置基于未来的 MT 代码(offtopic,用于说明):
CompletionService<YourCallableImplementor> completionService =
new ExecutorCompletionService<YourCallableImplementor>(service);
ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
for (String computeMe : elementsToCompute) {
futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
}
Then you need to keep track on how many results you expect and retrieve them like this:
然后您需要跟踪您期望的结果数量并像这样检索它们:
try {
int received = 0;
while (received < elementsToCompute.size()) {
Future<YourCallableImplementor> resultFuture = completionService.take();
YourCallableImplementor result = resultFuture.get();
received++;
}
} finally {
service.shutdown();
}
回答by Ravindra babu
Option 1:
选项1:
newWorkStealingPoolfrom Executors
newWorkStealingPool来自Executors
public static ExecutorService newWorkStealingPool()
Creates a work-stealing thread pool using all available processors as its target parallelism level.
使用所有可用的处理器作为其目标并行度级别来创建窃取工作的线程池。
With this API, you don't need to pass number of cores to ExecutorService
.
使用此 API,您无需将内核数传递给ExecutorService
.
Implementation of this API from grepcode
从grepcode实现这个 API
/**
* Creates a work-stealing thread pool using all
* {@link Runtime#availableProcessors available processors}
* as its target parallelism level.
* @return the newly created thread pool
* @see #newWorkStealingPool(int)
* @since 1.8
*/
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
Option 2:
选项 2:
newFixedThreadPoolAPI from Executors
or other newXXX constructors
, which returns ExecutorService
newFixedThreadPoolAPI 来自Executors
或other newXXX constructors
,它返回ExecutorService
public static ExecutorService newFixedThreadPool(int nThreads)
replace nThreads withRuntime.getRuntime().availableProcessors()
将 nThreads 替换为Runtime.getRuntime().availableProcessors()
Option 3:
选项 3:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
pass Runtime.getRuntime().availableProcessors()
as parameter to maximumPoolSize
.
Runtime.getRuntime().availableProcessors()
作为参数传递给maximumPoolSize
.