下水道井盖为什么是圆的

“下水道井盖是圆的,因为圆形不会掉进井口,而且圆形具有均匀分布压力的优势。”

如何写一个程序让 cpu 占用率保持在 50%?

不要用 if-else 来解决,要把比例转成不同的 worktime

解法的精确与否其实取决于“多久时间内测度一次已占用的时间”和“睡眠”两类 api 的精度。

bash 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# 精简版CPU负载控制器

L=${1:-50} # 默认50%
[ $L -lt 0 ] || [ $L -gt 100 ] && { echo "用法: $0 [0-100]"; exit 1; }

echo "CPU负载${L}%,Ctrl+C停止"
trap 'echo -e "\n停止"' INT

while true; do
for i in $(seq $L); do : > /dev/null; done
[ $((100-L)) -gt 0 ] && sleep 0.0$((100-L))
done

用法:

1
2
3
4
chmod +x cpu.sh
./cpu.sh 90 # 90%负载
./cpu.sh 30 # 30%负载
./cpu.sh # 50%负载(默认)

java 版本

单核

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class SimpleCPULoader {
public static void main(String[] args) {
// 默认50%利用率
double targetLoad = 0.5;

// 解析命令行参数
if (args.length > 0) {
try {
targetLoad = Double.parseDouble(args[0]) / 100.0;
// 限制范围在0-1之间
targetLoad = Math.max(0.0, Math.min(1.0, targetLoad));
} catch (NumberFormatException e) {
System.err.println("参数格式错误,使用默认50%负载");
}
}

System.out.println("开始CPU负载测试,目标利用率: " + (targetLoad * 100) + "%");
System.out.println("按 Ctrl+C 停止");

// 执行CPU负载控制
executeCPULoad(targetLoad);
}

private static void executeCPULoad(double loadRatio) {
final long PERIOD_MS = 100; // 100ms周期

while (true) {
long workTime = (long) (PERIOD_MS * loadRatio);
long sleepTime = PERIOD_MS - workTime;

// 工作阶段 - 消耗CPU
long workStart = System.currentTimeMillis();
while (System.currentTimeMillis() - workStart < workTime) {
// 空循环消耗CPU
Math.sqrt(Math.random());
}

// 休息阶段 - 让出CPU
try {
if (sleepTime > 0) {
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
System.out.println("\n程序被中断");
return;
}
}
}
}

多核

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MultiCoreCPULoader {
public static void main(String[] args) {
// 默认50%利用率
double targetLoad = 0.5;
// 默认使用所有CPU核心
int cores = Runtime.getRuntime().availableProcessors();

// 解析命令行参数
for (int i = 0; i < args.length; i++) {
try {
if (args[i].equals("-load") && i + 1 < args.length) {
targetLoad = Double.parseDouble(args[++i]) / 100.0;
targetLoad = Math.max(0.0, Math.min(1.0, targetLoad));
} else if (args[i].equals("-cores") && i + 1 < args.length) {
cores = Integer.parseInt(args[++i]);
cores = Math.max(1, Math.min(cores, Runtime.getRuntime().availableProcessors()));
}
} catch (NumberFormatException e) {
System.err.println("参数格式错误");
printUsage();
return;
}
}

System.out.println("开始CPU负载测试");
System.out.println("目标利用率: " + (targetLoad * 100) + "%");
System.out.println("使用核心数: " + cores);
System.out.println("按 Ctrl+C 停止");

// 执行多核CPU负载控制
executeMultiCoreCPULoad(targetLoad, cores);
}

private static void executeMultiCoreCPULoad(double loadRatio, int cores) {
ExecutorService executor = Executors.newFixedThreadPool(cores);

// 为每个核心启动一个工作线程
for (int i = 0; i < cores; i++) {
final int coreId = i;
executor.submit(() -> {
System.out.println("核心 " + coreId + " 开始工作");
executeSingleCoreCPULoad(loadRatio);
});
}

// 等待中断信号
try {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("\n正在停止所有核心...");
executor.shutdown();
try {
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}));

// 保持主线程运行
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
System.out.println("\n程序被中断");
executor.shutdownNow();
}
}

private static void executeSingleCoreCPULoad(double loadRatio) {
final long PERIOD_MS = 100; // 100ms周期

while (!Thread.currentThread().isInterrupted()) {
long workTime = (long) (PERIOD_MS * loadRatio);
long sleepTime = PERIOD_MS - workTime;

// 工作阶段 - 消耗CPU
long workStart = System.currentTimeMillis();
while (System.currentTimeMillis() - workStart < workTime &&
!Thread.currentThread().isInterrupted()) {
// 空循环消耗CPU
Math.sqrt(Math.random());
}

// 休息阶段 - 让出CPU
try {
if (sleepTime > 0) {
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}

private static void printUsage() {
System.out.println("用法: java MultiCoreCPULoader [选项]");
System.out.println("选项:");
System.out.println(" -load <百分比> 设置CPU负载 (0-100),默认50");
System.out.println(" -cores <数量> 指定使用的核心数,默认使用所有核心");
System.out.println("示例:");
System.out.println(" java MultiCoreCPULoader -load 90 # 90%负载,所有核心");
System.out.println(" java MultiCoreCPULoader -load 70 -cores 2 # 70%负载,2个核心");
System.out.println(" java MultiCoreCPULoader # 50%负载,所有核心");
}
}

多核和单核的差别是每个核用一个单独线程来处理 load,但是核心思路还是在 workTime 里面用一个 sqrt 的方法来对随机数开平方,其余时间睡眠。

正弦函数版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class SineWaveCPULoader {
private static final long PERIOD_MS = 100; // 控制周期100ms
private static final int FREQUENCY = 1; // 频率1Hz(每秒一个完整波形)

public static void main(String[] args) {
System.out.println("开始生成正弦波CPU负载...");
System.out.println("波形频率: " + FREQUENCY + "Hz");
System.out.println("按 Ctrl+C 停止");

generateSineWave();
}

private static void generateSineWave() {
long startTime = System.currentTimeMillis();

while (true) {
long currentTime = System.currentTimeMillis();

// 计算时间(秒)
double timeInSeconds = (currentTime - startTime) / 1000.0;

// 生成正弦波值: sin(2πft)
// f = FREQUENCY, t = timeInSeconds
double sineValue = Math.sin(2 * Math.PI * FREQUENCY * timeInSeconds);

// 将正弦波值 [-1,1] 映射到负载比例 [0.1, 0.9]
// 避免0%和100%极端值以保证稳定性
double loadRatio = 0.5 + 0.4 * sineValue;

// 执行CPU负载控制
executeCPULoad(loadRatio);

// 每2秒显示一次当前状态
if ((currentTime / 2000) % 1 == 0) {
System.out.printf("\r时间: %.1fs, 正弦值: %.2f, CPU负载: %.1f%%",
timeInSeconds, sineValue, loadRatio * 100);
System.out.flush();
}
}
}

private static void executeCPULoad(double loadRatio) {
long workTime = (long) (PERIOD_MS * loadRatio);
long sleepTime = PERIOD_MS - workTime;

// 工作阶段 - 消耗CPU
long workStart = System.currentTimeMillis();
while (System.currentTimeMillis() - workStart < workTime) {
// 空循环消耗CPU
Math.sqrt(Math.random());
}

// 休息阶段 - 让出CPU
try {
if (sleepTime > 0) {
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
System.out.println("\n程序被中断");
System.exit(0);
}
}
}

这个算法的核心是计算距离起点的距离,然后推算出这个阶段的点在正弦曲线上的的纵轴多高,然后再用 executeCPULoad 函数来操纵 CPU。

利用系统 cpu 的解

如果能够获取当前的 cpu 利用率,sleep一个最小循环,然后进到下个 while 里再获取一次。

利用cpu的理论执行时间

1
2
3
4
5
6
7
8
9
10
11
12
13
const DWORD  _busyTime = 10;
const DWORD _idleTime = _busyTime;
_int64 _startTime = 0;
void letCpuControl_GetTickCount()
{
while(true)
{
DWORD startTime = GetTickCount();//更新开始时间为系统开启到现在经历的时间
// 10ms 的精度渐进式地寻找 GetTickCount() 逼近一个目标时间区间
while(GetTickCount() - startTime <= _busyTime);//总时间 - 开始时间
_sleep(_idleTime);
}
}

一个屋子有一个门(门是关闭的)和3盏电灯。屋外有3个开关,分别与这3盏灯相连。你可以随意操纵这些开关,可一旦你将门打开,就不能变换开关了。确定每个开关具体管哪盏灯?

答:将一盏灯开一段时间,再关掉,在剩余2盏灯里随机开一盏,进屋去看,发热的灯对应第一个碰的开关,亮着的灯对应开关开着的开关,灭的灯对应没碰过的开关。