java - 强制多个线程在可用时使用多个 CPU

标签 java concurrency multithreading multicore

我正在编写一个使用大量 CPU 的 Java 程序,因为它的工作性质。但是,其中很多可以并行运行,并且我已经使我的程序成为多线程的。当我运行它时,它似乎只使用一个 CPU,直到它需要更多然后它使用另一个 CPU - 我可以在 Java 中做些什么来强制不同的线程在不同的内核/CPU 上运行?

最佳答案

在 Java 中有两种基本的多线程方式。您使用这些方法创建的每个逻辑任务都应在需要且可用时在新内核上运行。

方法一:定义一个 Runnable 或 Thread 对象(可以在构造函数中取一个 Runnable)并使用 Thread.start() 方法启动它运行。它将在操作系统为其提供的任何内核上执行——通常是负载较少的内核。

教程:Defining and Starting Threads

方法二:定义实现Runnable(如果它们不返回值)或Callable(如果它们返回值)接口(interface)的对象,其中包含您的处理代码。将这些作为任务从 java.util.concurrent 包传递给 ExecutorService。 java.util.concurrent.Executors 类有很多方法来创建标准的、有用的 ExecutorServices。 Link执行者教程。

根据个人经验,Executors 固定和缓存线程池非常好,尽管您需要调整线程数。 Runtime.getRuntime().availableProcessors() 可用于在运行时计算可用内核数。您需要在应用程序完成后关闭线程池,否则应用程序不会退出,因为 ThreadPool 线程仍在运行。

获得良好的多核性能有时很棘手,而且充满了陷阱:

  • 磁盘 I/O 在运行时会减慢很多 平行。一次只能有一个线程读取/写入磁盘。
  • 对象同步可为多线程操作提供安全性,但会减慢工作速度。
  • 如果任务太多 琐碎的(小工作位,执行 快速)管理它们的开销 在 ExecutorService 中的成本超过 您可以从多个内核中获益。
  • 创建新的 Thread 对象很慢。如果可能,ExecutorServices 将尝试重用现有线程。
  • 当多个线程处理某事时,可能会发生各种疯狂的事情。让您的系统保持简单,并尝试使任务在逻辑上不同且不交互。

另一个问题:控制工作很难!一个好的做法是有一个创建和提交任务的管理器线程,然后有几个带有工作队列的工作线程(使用 ExecutorService)。

这里我只是谈到了关键点——多线程编程被许多专家认为是最难的编程主题之一。它不直观、复杂,而且抽象通常很弱。


编辑——使用 ExecutorService 的示例:

public class TaskThreader {
    class DoStuff implements Callable {
       Object in;
       public Object call(){
         in = doStep1(in);
         in = doStep2(in);
         in = doStep3(in); 
         return in;
       }
       public DoStuff(Object input){
          in = input;
       }
    }

    public abstract Object doStep1(Object input);    
    public abstract Object doStep2(Object input);    
    public abstract Object doStep3(Object input);    

    public static void main(String[] args) throws Exception {
        ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        ArrayList<Callable> tasks = new ArrayList<Callable>();
        for(Object input : inputs){
           tasks.add(new DoStuff(input));
        }
        List<Future> results = exec.invokeAll(tasks);
        exec.shutdown();
        for(Future f : results) {
           write(f.get());
        }
    }
}

关于java - 强制多个线程在可用时使用多个 CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1223072/

相关文章:

java - 等待 JUnit 测试用例中测试的代码生成的所有线程

java - 如何打开并运行已编译的 Java 文件?

java - 每当调用某个类的方法时,我可以要求 java 执行某些操作吗

c# - 轮询新文件,在处理文件时避免重复

c++ - 为了执行TBB?

java - JAVA中跨线程统一分割目录中的文件

java - 在其模块中访问 Guice 注入(inject)器?

java - 务实地允许用户选择要运行的 JUnit 测试类

ios - 如何使一个代码仅在另一个代码在 Swift 中完成后运行

java - 使用 Jbutton 停止线程 (Java)