我一直在围绕多线程和多任务进行一些实验,我有几个问题。
1)考虑只有一个CPU核心/处理器的机器。运行多个线程并行是通过时间切片实现的(每个线程在CPU上运行几毫秒),如果一个线程在I / O上被阻塞,其他线程就可以运行,从而给人留下印象同时做多件事。
考虑相同的单处理器CPU,并说有两个线程,这两个线程都是CPU密集型的,没有I / O. 每个都需要5秒钟才能完成其操作。顺序运行将显然需要10秒。
并行运行它(使用执行程序服务)也需要10秒钟,因为线程只是CPU密集型的? (假设只有一个CPU核心)
2)在具有四个核心的计算机上,我有一项任务,独立运行需要5秒钟才能完成。我希望使用Java ProcessBuilder作为单独的进程并行运行其中几个(我不希望以并行线程的形式运行它们共享的对象)不是线程安全的,同步成本太高了)。 我预计它会在5秒左右完成。
开始两个并行过程并没有带来太大的改进,因为它们仍然需要大约9秒才能完成。这是为什么? (该任务是CPU密集型的并且消耗大量内存)。 注意:当我启动三个或四个进程时,延迟会越来越受到影响(更糟糕或等同于按顺序运行它们)。
修改
我的意图/问题更多地是为什么在使用进程时性能没有得到改善,而不是我是否应该在第二个问题中使用多个线程/进程。 对于问题2,(为了讨论起见),您可以简单地想象这样的任务:(虽然上面提到的问题中提到的数字不是来自下面的代码段)
String s;
for (int i = 0; i < 50000; i++) {
s += i; //consumes a lot of memory
}
long result = 0;
for(int j = 0; j < 3; j++) {
for (double i = 0; i < 500000000; i++) { //Lot of CPU
result += i;
}
}
答案 0 :(得分:1)
Answer to your 1st question:
过程/线程突发图如下所示
I / O ==&gt; CPU ==&gt; I / O ===&gt; CPU ==&gt; ...... I / O ..... ==&gt; CPU ==&gt; I / O
很明显,它们将以I / O burts开始和结束。单个处理器上的多处理/线程化只能以时间多路复用的方式实现,就像你说的那样。
来到你的问题: 这里两个作业/线程都是CPu绑定作业,并且不包含任何内部I / O(参见上面提到的流程)操作。因此,可能需要与顺序设置相同的时间。如果你有很多线程以相同的方式运行,那么没有任何内部I / O绑定操作可能比顺序访问花费更多的时间,因为在上下文切换中花费了大量的时间。
由于这种情况,LongTerm Scheduler被设计和编程为在就绪队列中放置I / O绑定和Cpu绑定作业的适当组合。
答案 1 :(得分:1)
并行运行(使用执行程序服务)也需要10 因为线程只是CPU密集型的秒数? (鉴于有 只有一个CPU核心)
原则上,没有。通过并行运行它们,你必须在上下文切换中浪费一些时间,所以从理论上讲,它们需要超过10秒。实际上,差异很难被发现,因为来自两个进程(或线程)的额外负载可能不会对CPU的争用产生足够的影响,从而导致切换损失明显增加。
开始两个平行过程并没有带来太大的改善 仍然需要大约9秒才能完成。这是为什么? (任务是 CPU密集型并消耗大量内存)。注意:当我开始 三个或四个过程,延迟越来越受到影响(更糟糕的是 或相当于按顺序运行它们。
您的实验受到启动两个或多个流程而不仅仅是一个流程的开销的影响,因此在此尝试得出任何结论实际上是无用的(除非您特别注意精确测量计算部分的计算部分)任务。)
答案 2 :(得分:0)
您正在运行多少个操作?由于通信开销,性能可能不会提高很多。因为一切都有成本,协调并行任务所需的时间可能占用了实际解决问题所花费的时间,使得不再有利于并行化代码。