Java多线程应用程序仅使用一个Core

时间:2014-01-22 17:35:24

标签: java multithreading performance jvm executor

我的JVM在带有openJDK 1.7.0_51 64Bit的CentOS 6.0上运行时出现问题。 我的系统是一个4核系统,配备8GB Ram。

我正在运行我自己编写的Java多线程应用程序。它应该将大量数据插入NoSQL数据库。 为此,我使用java.concurrent.Executors中的“CachedThreadPoolExecutor”生成4个线程。

我实例化了4个实现“Runnable”接口的Worker。然后我使用线程池执行Thread。这是我的代码:

 public void startDataPump(int numberOfWorkers){
   //class "DataPump" implements runnable
   for (int i = 0; i < numberOfWorkers; i++){
      DataPump pump = new DataPump();
      //"workerList" contains all workers and is a simple arrayList to keep track of the workers
      workerList.add(pump);
      //"workers" is the thradpool that has been 
      //initialized earlier with "Executors.newCachedThreadPool()
      workers.execute(pump);
   }
 }

运行此参数时,使用参数4,它将在Threadpool中生成4个Threads。我假设JVM或我的操作系统足够聪明,可以在我的所有内核上安排这些线程。 但是,只有我的cpu的一个核心工作在100%,其他核心几乎无所事事。

我在代码中做错了什么,或者这是一个JVM / OS问题。如果是这样,我能做些什么吗? 仅在1个核心上运行此应用程序极其缓慢了整个应用程序。

非常感谢帮助:)

3 个答案:

答案 0 :(得分:4)

请记住它的操作系统,而不是负责CPU亲和力的JVM - 这就是为什么我建议你先弄清楚你有多少CPU然后使用schedutil来配置某个进程的处理器关联。

cpu info - 使用以下三个中的一个

/proc/cpuinfo
lscpu
nproc

安装计划以配置处理器关联性

yum install schedutils  

您可以通过schedutils分配cpu affinity,如下所示(2是第二个procccor,23564是进程ID):

taskset -c 2 -p 23564

答案 1 :(得分:1)

调度线程不是JVM活动,而是操作系统活动。如果操作系统发现线程彼此独立,可以单独执行,然后将其安排在另一个核心上。

我不确定schedutils但我认为它适用于应用程序级别(它允许你设置cpu亲和力,但最后的决定是由OS采取的)

关于使用内核的一件事是OS调度程序在新内核上安排新进程,因为每个进程都有自己独立于其他进程的进程区域(因此它们可以平行执行而不受任何阻碍)

尝试为每个线程创建新进程,以帮助提高cpu利用率(使用更多内核),但也有缺点,每个进程都创建自己的进程区域,因此每个进程都需要额外的内存(对于每个线程)在你的情况下)如果你有足够的可用内存,那么你可以试试这个。

如果它只是一个Linux操作系统,那么“sar”命令足以监控每个核心的CPU利用率(sar是linux中的基础包,几乎所有实用程序都使用'sar',因此系统上的开销会更少)。

答案 2 :(得分:0)

如果您的环境是虚拟的,或者使用诸如docker之类的特殊cpu调度,则无法让Java自动使用来查找可用的许多内核并全部使用它们。您必须通过

指定要使用多少个内核
  

在JDK> = 10上,使用以下JDK选项:

     

-XX:ActiveProcessorCount = 2

     

在JDK> = 8上,使用以下JDK选项:

     

-XX:+ UnlockExperimentalVMOptions> -XX:ActiveProcessorCount = 2