Java:如何根据cpu核心扩展线程?

我不是一个好的java程序员,这只是我的爱好,但我渴望知道更多的东西。

我想用java中的多个线程来解决一个math问题。 我的math问题可以分解成单位,我想在几个线程中解决。

但是我不想有固定数量的线程在其上工作,而是相当于cpu核心数量的线程数量。 而我的问题是,我无法在互联网上find一个简单的教程。 我发现的都是固定线程的例子。

那么你能帮我一个好的方法吗?或者可以给我一个简单而又好的例子? 这将是非常好的:)

您可以通过使用静态运行时方法availableProcessors来确定可用于Java虚拟机的进程数。 一旦确定了可用处理器的数量,就可以创build这个线程数量并相应地分配工作。

更新 :为了进一步说明,一个线程只是Java中的一个对象,所以你可以像创build任何其他对象一样创build它。 所以,假设你调用上面的方法,并发现它返回2个处理器。 真棒。 现在,您可以创build一个循环来生成一个新的线程,并将该线程的工作分开,然后触发线程。 这里有一些伪代码来说明我的意思:

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(); } 

有关创build自己的线程的更多信息,请参阅本教程 。 此外,您可能需要查看线程池的创build线程。

你可能也想看看这个东西的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 } }); 

要么

  Future<String> future = pool.submit(new Callable<String>() { public String call() throws Exception { return null; } }); future.get(); // Will block till result available 

这比应付你自己的线程池好得多

Doug Lea(并发软件包的作者)有这篇文章可能是相关的: http : //gee.cs.oswego.edu/dl/papers/fj.pdf

Fork Join框架已经添加到Java SE 7中。下面是更多的参考资料:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html Article by Brian Goetz

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

在Runtime类中,有一个名为availableProcessors()的方法。 你可以用它来确定你有多less个CPU。 由于你的程序是CPU绑定的,所以你可能希望每个可用的CPU有(最多)一个线程。

选项1:

来自Executors newWorkStealingPool

 public static ExecutorService newWorkStealingPool() 

使用所有可用的处理器创build工作线程池作为其目标并行级别。

有了这个API,您不需要将内核数量传递给ExecutorService

从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); } 

选项2:

来自Executors newFixedThreadPool API或other newXXX constructors返回ExecutorService other newXXX constructors

 public static ExecutorService newFixedThreadPool(int nThreads) 

Runtime.getRuntime().availableProcessors() replacenThreads。availableProcessors Runtime.getRuntime().availableProcessors()

备选案文3:

的ThreadPoolExecutor

 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) 

Runtime.getRuntime().availableProcessors()作为parameter passing给maximumPoolSize

标准的方法是Runtime.getRuntime()。availableProcessors()方法。 在大多数标准CPU上,您将在此返回最佳线程数(这不是实际的CPU内核数)。 所以这就是你要找的。

例:

 ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 

不要忘记closures这样的执行器服务(或者你的程序不会退出):

 service.shutdown(); 

这里简单介绍一下如何build立一个基于未来的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))); } 

那么你需要跟踪你期望得到的结果和检索他们是这样的:

 try { int received = 0; while (received < elementsToCompute.size()) { Future<YourCallableImplementor> resultFuture = completionService.take(); YourCallableImplementor result = resultFuture.get(); received++; } } finally { service.shutdown(); }