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

And*_*nig 101 java multithreading cpu-cores

我不是一个优秀的java程序员,这只是我的爱好,但我渴望知道的不仅仅是普通的东西.

我想解决java中多线程的数学问题.我的数学问题可以分成工作单元,我想在几个线程中解决.

但是我不希望有一定数量的线程处理它,而是相应的线程数量与cpu核心量相对应.我的问题是,我在互联网上找不到一个简单的教程.我找到的只是固定线程的例子.

那么你能帮助我找到一个好的tuturial的链接或者能给我一个简单而好的例子吗?那会非常好:)

Jas*_*Cav 114

您可以使用静态运行时方法availableProcessors确定Java虚拟机可用的进程数.一旦确定了可用的处理器数量,就创建该数量的线程并相应地拆分您的工作.

更新:为了进一步说明,Thread只是Java中的一个Object,因此您可以像创建任何其他对象一样创建它.所以,假设你调用上面的方法并发现它返回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();
}
Run Code Online (Sandbox Code Playgroud)

有关创建自己的线程的更多信息,请转到本教程.此外,您可能希望查看线程池以创建线程.

  • 这基本上是正确的,但要注意使用英特尔"超线程"销售的处理器的性能.在四核上,这将返回8而不是4,但你的性能实际上可能会在4个线程后开始下降 - 所以我自己的基准测试告诉我:) (17认同)
  • 请看这里的示例:http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ExecutorService.html它将告诉您更简化的方法来创建和管理线程池......一开始可能看起来更复杂,但与大多数事情一样,它更复杂,因为如果它更简单,你就会更快地达到限制. (5认同)

Dav*_*veC 62

你可能也想看看这个东西的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
        }
    });
Run Code Online (Sandbox Code Playgroud)

要么

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

这比处理自己的线程池等要好得多.

  • 具有可用处理器数量的固定大小池通常最适合CPU绑定进程.这里的第一个例子是你需要做的. (4认同)
  • java.util.concurrent具有高度可伸缩性 (3认同)

Dav*_*oko 8

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 文章来自Brian Goetz

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


fl0*_*l0w 7

标准方法是 Runtime.getRuntime().availableProcessors() 方法。在大多数标准 CPU 上,您将在此处返回最佳线程数(不是实际的 CPU 核心数)。因此,这就是您正在寻找的。

例子:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Run Code Online (Sandbox Code Playgroud)

不要忘记像这样关闭执行器服务(否则你的程序将不会退出):

service.shutdown();
Run Code Online (Sandbox Code Playgroud)

这里只是快速概述如何设置基于未来的 MT 代码(题外话,用于说明):

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)));
    }
Run Code Online (Sandbox Code Playgroud)

然后您需要跟踪您期望的结果数量并像这样检索它们:

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

  • shutdown 调用应该放在 try finally 中 (2认同)

Rav*_*abu 7

选项1:

newWorkStealingPool来自Executors

public static ExecutorService newWorkStealingPool()
Run Code Online (Sandbox Code Playgroud)

使用所有可用处理器作为其目标并行度级别创建工作窃取线程池.

使用此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);
    }
Run Code Online (Sandbox Code Playgroud)

选项2:

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

public static ExecutorService newFixedThreadPool(int nThreads)
Run Code Online (Sandbox Code Playgroud)

用.替换nThreads Runtime.getRuntime().availableProcessors()

选项3:

的ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)
Run Code Online (Sandbox Code Playgroud)

传递Runtime.getRuntime().availableProcessors()给参数maximumPoolSize.