Java如何利用多个核心?


74

JVM在单个进程中运行,并且JVM中的线程共享属于该进程的堆。那么JVM如何利用提供多个OS线程以实现高并发性的多个内核?


4
据我所知,Java线程是本机OS线程(在大多数JVM中)。他们没什么特别的。
Sasha Chedygov

4
本机应用程序线程也可以在单个进程中运行,并共享公用的内存分配(并且仍可以使用多个内核)。
Thilo 2010年

Answers:


34

您可以使用多个线程来使用多个核心。但是,使用比计算机中存在的内核数更多的线程数,只会浪费资源。您可以使用availableProcessors()来获取核心数量。

Java 7中,存在使用多个内核的fork / join框架

相关问题:


5
机器通常只有2个或4个处理器。您曾说过:“使用比计算机中存在的内核数更多的线程数只会浪费资源”,这是否意味着我们应该只有大约2或4个线程才能最大化性能?
Pacerier 2014年

2
“但是使用比计算机中存在的内核数更多的线程数只会浪费资源。” 在一般情况下,这没有任何意义。如果您拥有的线程数多于核心数,则这些线程将分布在这些核心中,并像其他任何正在运行的线程/进程一样,获得它们在给定核心中的份额,从而使进程取得进展,这肯定比做线程更有效。按顺序工作。
ChiefTwoPencils 16/09/23

@ ChiefTwoPencils; 如果我们有两个应用程序,并且每个应用程序有6个线程在4个CPU内核上运行。在这种情况下,任务将如何在这些CPU之间分配?单个应用程序中的另一个问题6个线程正在4个CPU上运行,这6个线程将在这4个CPU上并行运行还是在多个线程之间进行交错操作
user3094331

是真的,如果您在Tomcat(例如在Java 8上)上运行Web应用程序(其中每个传入的HTTP请求都由Java-Thread处理),则Web应用程序会自动受益于多个内核,对吗?今天,您可以租用32核AMD机器,对我来说运行Web应用程序听起来很完美。当然:云是另一种选择,但是我现在谈论的是专用服务器...有什么意见吗?
basZero

23

JVM在单个进程中运行,并且JVM中的线程共享属于该进程的堆。那么JVM如何利用提供多个OS线程以实现高并发性的多个内核?

如果在多CPU机器上运行,Java将利用底层OS的线程来完成在不同CPU上执行代码的实际工作。当每个Java线程启动时,它创建了一个相关的操作系统线程和OS负责调度等。JVM的某些做一些管理和喜欢的线程和Java语言结构的跟踪volatilesynchronizednotify()wait(),等所有影响运行操作系统线程的状态。

JVM在单个进程中运行,并且JVM中的线程共享属于该进程的堆。

JVM不必“在单个进程中运行”,因为即使垃圾回收器和其他JVM代码在不同的线程中运行,并且OS经常将这些不同的线程表示为不同的进程。例如,在Linux中,您在进程列表中看到的单个进程通常会伪装一堆不同的线程进程。即使您在单核计算机上,也是如此。

但是,您是正确的,它们都共享相同的堆空间。它们实际上共享相同的整个内存空间,这意味着代码,内部字符串,堆栈空间等。

那么JVM如何利用提供多个OS线程以实现高并发性的多个内核?

线程的性能提高有两个原因。显然,直接并发通常会使程序运行得更快。能够同时执行多个CPU任务(尽管并非总是如此)可以提高应用程序的吞吐量。您还可以将IO操作隔离到单个线程,这意味着当一个线程正在等待IO(读/写到磁盘/网络等)时,其他线程也可以运行。

但是就内存而言,线程由于本地每CPU缓存的内存而获得了很多性能提升。当线程在CPU上运行时,CPU的本地高速内存缓存可帮助线程在本地隔离存储请求,而不必花费时间来读取或写入中央内存。这就是为什么volatile并且synchronized调用包含内存同步结构的原因,因为当线程需要协调其工作或彼此通信时,必须将高速缓存存储器刷新到主存储器或使其无效。


谢谢您的回答-但我有一个要求:如果您可以在每次使用“线程”之前加上“ OS”或“ Java”前缀,那将非常有帮助。术语冲突对我来说非常令人困惑(我也可能猜想其他人),如果我说我现在真的很明白这件事,那我会撒谎。
Niki Herl,

1
@NikiHerl的全部要点是Java线程具有OS线程等效项。如果我没有指定线程的类型,那就没关系了。例如,当我谈论将IO隔离到单个线程时,这是指正在执行工作的JVM线程和OS线程。
灰色

21

在Java 1.2中,绿色线程被本地线程替换。


3
+1-换句话说,操作系统将根据系统调度和资源管理约束来安排使用不同内核的不同Java线程。
斯蒂芬·C

21

如果操作系统通过可用处理器分配线程,则Java将受益于多个内核。JVM本身并没有做任何特别的事情来使其线程在多个内核之间平均调度。请记住以下几点:

  • 在实现并行算法时,最好生成与内核一样多的线程。(Runtime.getRuntime().availableProcessors())。不多不少。
  • 利用 java.util.concurrent包装。
  • 确保您的个人库中有Java Concurrency in Practice

1
不多,不少。不正确 按照您建议的书,应该生成一个(处理器数量+ 1),因为当某个线程正在执行IO时,多余的线程可以利用空闲的CPU
garg10may

2
线程只是在做一些处理,而不是在等待任何远程调用(例如数据库,远程API,JMS等),因此上述建议很有意义。但是实际上,所有常规应用程序都使用远程调用。因此,最佳线程数可以根据远程调用的延迟而有所不同。做负载测试并决定。
Venkateswara Rao
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.