下水道井盖为什么是圆的
“下水道井盖是圆的,因为圆形不会掉进井口,而且圆形具有均匀分布压力的优势。”
如何写一个程序让 cpu 占用率保持在 50%?
不要用 if-else 来解决,要把比例转成不同的 worktime。
解法的精确与否其实取决于“多久时间内测度一次已占用的时间”和“睡眠”两类 api 的精度。
bash 版本
1 2 3 4 5 6 7 8 9 10 11 12 13
| #!/bin/bash
L=${1:-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 ./cpu.sh 30 ./cpu.sh
|
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) { double targetLoad = 0.5; if (args.length > 0) { try { targetLoad = Double.parseDouble(args[0]) / 100.0; 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 停止"); executeCPULoad(targetLoad); } private static void executeCPULoad(double loadRatio) { final long PERIOD_MS = 100; while (true) { long workTime = (long) (PERIOD_MS * loadRatio); long sleepTime = PERIOD_MS - workTime; long workStart = System.currentTimeMillis(); while (System.currentTimeMillis() - workStart < workTime) { Math.sqrt(Math.random()); } 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) { double targetLoad = 0.5; 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 停止"); 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; while (!Thread.currentThread().isInterrupted()) { long workTime = (long) (PERIOD_MS * loadRatio); long sleepTime = PERIOD_MS - workTime; long workStart = System.currentTimeMillis(); while (System.currentTimeMillis() - workStart < workTime && !Thread.currentThread().isInterrupted()) { Math.sqrt(Math.random()); } 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; private static final int FREQUENCY = 1; 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; double sineValue = Math.sin(2 * Math.PI * FREQUENCY * timeInSeconds); double loadRatio = 0.5 + 0.4 * sineValue; executeCPULoad(loadRatio); 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; long workStart = System.currentTimeMillis(); while (System.currentTimeMillis() - workStart < workTime) { Math.sqrt(Math.random()); } 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(); while(GetTickCount() - startTime <= _busyTime); _sleep(_idleTime); } }
|
一个屋子有一个门(门是关闭的)和3盏电灯。屋外有3个开关,分别与这3盏灯相连。你可以随意操纵这些开关,可一旦你将门打开,就不能变换开关了。确定每个开关具体管哪盏灯?
答:将一盏灯开一段时间,再关掉,在剩余2盏灯里随机开一盏,进屋去看,发热的灯对应第一个碰的开关,亮着的灯对应开关开着的开关,灭的灯对应没碰过的开关。