强制多个线程在可用时使用多个 CPU
我正在编写一个Java程序,由于它所做的性质,它使用了大量的CPU。但是,它中的很多都可以并行运行,并且我已经使我的程序成为多线程的。当我运行它时,它似乎只使用一个CPU,直到它需要更多,然后使用另一个CPU - 在Java中我可以做些什么来强制不同的线程在不同的内核/ CPU上运行?
我正在编写一个Java程序,由于它所做的性质,它使用了大量的CPU。但是,它中的很多都可以并行运行,并且我已经使我的程序成为多线程的。当我运行它时,它似乎只使用一个CPU,直到它需要更多,然后使用另一个CPU - 在Java中我可以做些什么来强制不同的线程在不同的内核/ CPU上运行?
在 Java 中,有两种基本的多线程方法。使用这些方法创建的每个逻辑任务都应在需要时和可用时在新的内核上运行。
方法一:定义一个 Runnable 或 Thread 对象(可以在构造函数中采用 Runnable),并使用 Thread.start() 方法启动它。它将在操作系统赋予它的任何核心上执行 - 通常是负载较少的内核。
教程:定义和启动线程
方法二:定义实现 Runnable(如果它们不返回值)或 Callable(如果它们返回值)接口的对象,其中包含您的处理代码。将这些任务作为任务从 java.util.concurrent 包传递到 ExecutorService。java.util.concurrent.Executors 类有一堆方法来创建标准的、有用的 ExecutorServices。链接到执行器教程。
从个人经验来看,执行器固定和缓存线程池非常好,尽管您需要调整线程计数。Runtime.getRuntime().availableProcessors() 可以在运行时用于计算可用内核的次数。应用程序完成后,您需要关闭线程池,否则应用程序不会退出,因为 ThreadPool 线程保持运行。
获得良好的多核性能有时很棘手,而且充满了陷阱:
另一个问题是:控制工作是困难的!一个好的做法是让一个管理器线程创建和提交任务,然后使用几个具有工作队列的工作线程(使用 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());
}
}
}