我正在编写一个使用大量 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/