gpt4 book ai didi

java - Multitheard的应用程序看起来可以随机运行

转载 作者:搜寻专家 更新时间:2023-11-01 03:02:31 24 4
gpt4 key购买 nike

我写了一个Java代码只是为了测试必须执行操作时我的CPU将如何运行,所以我写了一个循环,该循环将在1亿次迭代中向var加1:

public class NoThread {
public static void main(String[] args) {
long s = System.currentTimeMillis();
int sum = 0;
for (int i=0;i<=1000000;i++){
for (int j=0;j<=10000;j++){
for (int k = 0;k<=10;k++){
sum++;
}
}
}
long k = System.currentTimeMillis();
System.out.println("Time" + (k-s)+ " " + sum );
}
}

代码在30-40秒后完成工作。

接下来,我决定将此操作分成10个线程,以使我的cpu更加哭泣,并说我的编要在每个线程结束时写入时间:
public class WithThread {

public static void main(String[] args) {
Runnable[] run = new Runnable[10];
Thread[]thread = new Thread[10];
for (int i = 0; i<=9;i++){
run[i] = new Counter(i);
thread[i] = new Thread(run[i]);
thread[i].start();
}
}
}


public class Counter implements Runnable {
private int inc;
private int incc;
private int sum = 0;
private int id;
public Counter(int a){
id = a;
inc = a * 100000;
incc = (a+1)*100000;
}
@Override
public void run(){
long s = System.currentTimeMillis();
for (int i = inc;i<=incc;i++){
for (int j=0;j<=10000;j++){
for (int k = 0;k<=10;k++){
sum++;
}

}
}
long k = System.currentTimeMillis();
System.out.println("Time" + (k-s)+ " " + sum + " in thread " + id);
}
}

结果整个代码在18到20秒的时间内结束-快了两倍,但是当我在每个Thread端查看时间的时候,我发现了一些有趣的东西。每个线程都有相同的工作要做,但是4个线程在很短的时间(0.8秒)内结束工作,其余线程(6个)在18至20秒内结束。我再次启动它,现在我有6个线程,运行时间快,4个线程,运行慢。再次以7快和3慢的速度运行。快速线程和慢线程的数量是随机的。所以我的问题是,为什么快线程和慢线程之间会有如此大的差异。为什么快速线程和慢速线程的数量是如此随机,并且该语言是特定于Java(Java)还是操作系统,CPU或其他?

最佳答案

在进入线程和处理器的工作过程之前,我将以更易于理解的方式对其进行解释。

场景

Location A ------------------------------ Location B
| |_____________________________|
| |
| 200 Metres
|
| Have to be carried to
400 Bags of Sand -------------------------- Location B
(In Location A)

因此, worker 必须将每个沙袋从位置A搬运到位置B,直到将所有沙袋移动到位置B。

让我们假装该 worker 到达位置B后会立即被传送回位置A(出于争论的目的)到位置A(但不能反过来)。

案例1

员 worker 数= 1(男性人数)

花费的时间= 2分钟(将1个沙袋从位置A移动到位置B的时间)

从位置A到位置B携带 400 Sandbags所需的总时间为

总耗时= 2 x 400 = 800分钟

案例2

员 worker 数= 4(男性人数)

花费的时间= 2分钟(将1个沙袋从位置A移动到位置B的时间)

因此,现在我们将把工作平均分配给可用的劳动力。

每个 worker 分配的沙袋= 400/4 = 100

可以说每个人都在同时开始工作。

单个员工从地点A到地点B搬运100个沙袋所需的总时间

占用个人劳动力的时间= 2 x 100 = 200分钟

由于每个人都同时开始工作,因此所有的 400 Sandbags都将通过 200 mins从位置A携带到位置B。

案例3

员 worker 数= 4(男性人数)

在这里,可以说每个人必须在一次转移中从位置A到位置B携带4个沙袋。

每名 worker 单次转运的沙袋总数= 4袋

花费的时间= 12分钟(一次转移将4个沙袋从位置A移动到位置B的时间)

由于每个人都被迫携带4个沙袋而不是1个,这极大地降低了它们的速度。

即使考虑到这一点,

1)我命令您从A到B携带1个沙袋,您需要2分钟。

2)我命令您一次从A到B携带2个沙袋,所以您需要5分钟而不是理论上的4分钟,因为这是由于我们的 body 状况和我们所携带的重量而引起的。

3)我命令您一次从A到B携带4个沙袋,而不是(理论上在第1点需要8分钟,理论上在第2点需要10分钟)要花12分钟,这也是由于人的天性。

因此,现在我们将把工作平均分配给可用的劳动力。

每个 worker 分配的沙袋= 400/4 = 100

每个 worker 的总转移= 100/4 = 25次转移

计算单例 worker 完成其全部工作所需的时间

单例 worker 的总时间= 12分钟x 25次转移= 300

因此,他们花了额外的100分钟,而不是理论上的200分钟(案例2)

案例4

每名 worker 单次转运的沙袋总数= 100袋

由于任何人都不可能做到这一点,因此他将退出。
xx--------------------------------------------------------------------------------------xx

这与线程和处理器中的工作原理相同

这里

劳动力=处理器数量

沙包总数=线程数

一次传输中的 沙袋=线程数,(1)个处理器将同时处理

认为

可用处理器= 4
Runtime.getRuntime().availableProcessors()  // -> Syntax to get the no of available processors

注意:将每个案例与上面介绍的实时案例关联起来

案例1
for (int i=0;i<=1000000;i++){
for (int j=0;j<=10000;j++){
for (int k = 0;k<=10;k++){
sum++;
}
}
}

整个操作是一系列过程,因此将花费执行时间。

案例2
for( int n = 1; n <= 4; n++ ){  
Thread t = new Thread(new Runnable(){
void run(){
for (int i=0;i<=250000;i++){ // 1000000 / 4 = 250000
for (int j=0;j<=10000;j++){
for (int k = 0;k<=10;k++){
sum++;
}
}
}
}
});
t.start();
}

在这里,每个处理器将处理1个线程。因此,这将花费实际时间的1/4。

案例3
for( int n = 1; n <= 16; n++ ){  
Thread t = new Thread(new Runnable(){
void run(){
for (int i=0;i<=62500;i++){ // 1000000 / 16 = 62500
for (int j=0;j<=10000;j++){
for (int k = 0;k<=10;k++){
sum++;
}
}
}
}
});
t.start();
}

总共将创建16个线程,每个处理器将必须同时处理4个线程。因此,实际上,这会将处理器负载增加到最大,从而降低处理器效率,从而延长每个处理器的执行时间。

总共需要 1/4th of(1/4th of actual time) + performace degrade time(will definitely be higher than than the 1/4th of actual time)
案例4
for( int n = 1; n <= 100000; n++ ){       // 100000 - Just for argument sake
Thread t = new Thread(new Runnable(){
void run(){
for (int i=0;i<=1000000;i++){
for (int j=0;j<=10000;j++){
for (int k = 0;k<=10;k++){
sum++;
}
}
}
}
});
t.start();
}

在这个阶段,创建和启动线程要比创建和启动前一个线程花费更多的时间(如果处理器中已经有更多的线程)。随着同时线程数量的增加,它将极大地增加处理器的负载直到处理器达到其容量,从而导致系统崩溃。

在第一个线程中创建的线程执行时间更少的原因是,在初始阶段,处理器不会有任何性能下降。但是随着for循环的继续,每个处理器不必处理的线程数就不会超出公平比率(1:1),因此,当处理器中的线程数增加时,您将开始遇到延迟。

关于java - Multitheard的应用程序看起来可以随机运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32256588/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com