Java是否支持多核处理器/并行处理?

38

我知道现在大多数处理器都有两个或更多核心,多核编程非常流行。Java中是否有利用此功能的方法?我知道Java有Thread类,但是我也知道这个类早在多核变得流行之前就存在了。如果我想在Java中利用多个核心,我应该使用哪个类/技术?


2
我之前问过一个非常类似的问题:https://dev59.com/9nI_5IYBdhLWcg3wFu7L我建议你阅读那个问题的答案。 - Carl
@Carl:我更想了解关于功能而不是线程的旧用法。我特别想知道有关新类的信息(请注意,没有人用java.util.Concurrent回答你的问题)。 - Rafe Kettler
让我重新表述一下:你会使用类Thread / Callable(因为对于我问题的所有答案都指出,Thread / Callable在多核机器上“只是工作”)。 使用Thread / Callable通常也意味着使用java.util.concurrent - 但这与单核与多核实现无关。 - Carl
5个回答

44

Java是否支持多核处理器/并行处理?

是的。它也成为其他编程语言的平台,其中实现添加了“真正的多线程”或“真实线程”的卖点。在新版本中引入的G1垃圾收集器也利用了多核硬件。

Java并发编程实战

尝试获取一本Java并发编程实战书籍。


如果我想在Java中利用多核心,我应该使用哪个类/技术?

java.util.concurrent

实用类通常在并发编程中使用。该包含一些小型标准化可扩展框架,以及一些提供有用功能且其他情况下繁琐或难以实现的类。以下是主要组件的简要描述。

执行器

Executor是一个简单的标准化接口,用于定义自定义线程子系统,包括线程池、异步IO和轻量级任务框架。

队列

java.util.concurrent ConcurrentLinkedQueue类提供了一个高效可扩展的线程安全非阻塞FIFO队列。

计时

TimeUnit类提供多个粒度(包括纳秒)来指定和控制基于超时的操作。该包中的大多数类都包含基于超时的操作,以及无限等待。

同步器

四个类帮助常见的特殊目的同步习语。 Semaphore是一种经典的并发工具。 CountDownLatch是一种非常简单但非常常见的实用程序,可阻塞直到给定数量的信号、事件或条件保持。

并发集合

除了队列之外,该包还提供了一些集合实现,设计用于多线程上下文中使用:ConcurrentHashMapCopyOnWriteArrayListCopyOnWriteArraySet


如果你想将线程数与可用CPU数量匹配,这也非常方便:

int n = Runtime.getRuntime().availableProcessors();

9
在大多数Java实现中,您可以依赖于Java线程是真正的操作系统线程。因此,如果您使用Thread类,操作系统将确保工作负载在多个核心之间分配。
操作系统线程早在商品化的多核系统出现之前就存在了,所以这并不是一个真正的问题。多核系统唯一的区别是允许时间复用的操作系统线程在多个核心上作为真正的并发线程执行。

8
Java 5引入了java.util.concurrent包,它有助于构建可以从多核系统中受益的并发应用程序。该包远远超出了Java 1.4及之前提供的多线程功能(如synchronized、wait、notify等)。
Java 7有一个提案,包括Fork/Join框架,以使多核系统的使用更加容易。

2
您将在Ateji PX中找到新功能,它是Java语言的扩展,具有从pi演算中受启发的并行原语。这与线程编程以及所有基于线程的内容(任务、执行器等)非常不同。
在语言级别引入并行性,而不是提供API访问大多数基于硬件层面的线程库,使得多核编程变得更加简单和直观。
这是一种根本性的新方法,值得阅读(免责声明:我是Ateji PX的设计师)。白皮书在此处:http://www.ateji.com/px/whitepapers/Ateji%20PX%20for%20Java%20v1.0.pdf

0

是的。Java提供并发API以利用机器的多核处理器优势。

您可以从Runtime获取可用处理器数量,并使用该数量通过Executors中的许多API创建ExecutorService

您还可以使用ThreadPoolExecutor API来实现相同的功能。

Java 8提供了一个新的API:newWorkStealingPool,它通过使用所有可用处理器创建ForkJoinPool。您不必将处理器计数作为参数传递。

请查看代码示例:

int processorCount = Runtime.getRuntime().availableProcessors();

ExecutorService executor1 = Executors.newFixedThreadPool(processorCount);
ExecutorService executor2 =  
                            Executors.newScheduledThreadPool(processorCount);
ExecutorService executor3 = Executors.newWorkStealingPool(); // java-8 API
ForkJoinPool forkJoinPool = new ForkJoinPool(processorCount);

看一下相关的SE问题:正确的执行器:

Java的Fork/Join与ExecutorService-何时使用哪个?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接