要求:1000次循环在六秒左右,目前是九秒多,不到十秒。cmd执行命令的参数path是动态的,是批量执行脚本的命令,这里只是个demo。不同设备保证不会有乱码。回复里最好有现在慢的主要原因,解决思路及优化后的代码
static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
@GetMapping("/run")
public void run() {
String path = "ipconfig";
executorService.execute(() -> {
try {
Process process;
process = new ProcessBuilder("cmd.exe", "/c", path).start();
readStream(process.getErrorStream());
readStream(process.getInputStream());
//System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
} catch (IOException e) {
System.out.println("运行错误:" + e.getMessage());
e.printStackTrace();
}
});
}
public void readStream(InputStream is) {
String line;
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(is, "gbk"));
StringBuilder CmdReturn = new StringBuilder();
line = input.readLine();
while (line != null) {
line = input.readLine();
CmdReturn.append(line);
}
//System.out.println(CmdReturn);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
把完整代码贴出来吧,
你这功能是啥,不停扫描指定目录下的文件么?并做文件读取么?
C:\Users\Administrator.jdks\corretto-1.8.0_302\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.2\lib\idea_rt.jar=62978:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\charsets.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\access-bridge-64.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\cldrdata.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\dnsns.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\jaccess.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\jfxrt.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\localedata.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\nashorn.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\sunec.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\sunjce_provider.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\sunmscapi.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\sunpkcs11.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\ext\zipfs.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\jce.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\jfr.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\jfxswt.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\jsse.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\management-agent.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\resources.jar;C:\Users\Administrator.jdks\corretto-1.8.0_302\jre\lib\rt.jar;C:\Users\Administrator\IdeaProjects\Test001\out\production\Test001 com.company.Main
type 1 count 1000 starts at 2021-08-13 23:44:42:239
submit done at 2021-08-13 23:44:42:380
jobs done at 2021-08-13 23:45:03:611
cost time: 21372 ms
type 2 count 1000 starts at 2021-08-13 23:45:03:611
submit done at 2021-08-13 23:45:03:611
jobs done at 2021-08-13 23:45:16:078
cost time: 12467 ms
Process finished with exit code 0
package com.company;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
static ExecutorService executorService2 = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
public static void run2() {
String path = "C:\\Windows\\System32\\ipconfig.exe";
executorService2.execute(() -> {
try {
Process process;
process = new ProcessBuilder(path).start();
readStream(process.getErrorStream());
readStream(process.getInputStream());
//System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
} catch (IOException e) {
System.out.println("运行错误:" + e.getMessage());
e.printStackTrace();
}
});
}
public static void run() {
String path = "ipconfig";
executorService.execute(() -> {
try {
Process process;
process = new ProcessBuilder("cmd.exe", "/c", path).start();
readStream(process.getErrorStream());
readStream(process.getInputStream());
//System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
} catch (IOException e) {
System.out.println("运行错误:" + e.getMessage());
e.printStackTrace();
}
});
}
public static void readStream(InputStream is) {
String line;
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(is, "gbk"));
StringBuilder CmdReturn = new StringBuilder();
line = input.readLine();
while (line != null) {
line = input.readLine();
CmdReturn.append(line);
}
// System.out.println(CmdReturn);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public static void main(String[] args) {
// write your code here
int loopCount = 1000;
System.out.println( "type 1 count " + loopCount+ " starts at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
run();
}
System.out.println("submit done at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
executorService.shutdown();
while (!executorService.isTerminated()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("jobs done at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date(end)));
System.out.println("cost time: " + (end - start) + " ms");
System.out.println( "type 2 count " + loopCount+ " starts at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
long start2 = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
run2();
}
System.out.println("submit done at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
executorService2.shutdown();
while (!executorService2.isTerminated()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long end2 = System.currentTimeMillis();
System.out.println("jobs done at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date(end2)));
System.out.println("cost time: " + (end2 - start2) + " ms");
}
}
这个是创建进程执行命令,获取系统信息,与电脑性能有关,cpu 核心数越多性能越高,时间几乎都是进程启动上了
你具体需要这里面的哪些信息,可以不使用进程去获取,
能不能复用Process,感觉创建Process花费比较大
可以尝试调用系统api的方式直接调用系统命令肯定惠比较慢。
你用的是newFixed,固定数量,实际运行的命令超过fixed数量就会等待线程执行完毕才会执行剩余命令,换成cached看看吧
static ExecutorService executorService3 = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
public static void run3() {
String path = "ipconfig";
/**组装命令集合**/
List<String> allCommands = new ArrayList<>();
for(int i=1;i<1000;i++){
allCommands.add(path);
}
//按100条分组(也可以多点)
//Lists ---> guava工具包
//<dependency>
// <groupId>com.google.guava</groupId>
// <artifactId>guava</artifactId>
// <version>30.0-jre</version>
//</dependency>
List<List<String>> partition = Lists.partition(allCommands, 100);
for(List<String> commands : partition){
executorService3.execute(() -> {
try {
//利用一次执行多条命令 cmd /c 命令1 & 命令2 & 命令3
Process process = new ProcessBuilder("cmd.exe", "/c", StringUtils.join(commands.toArray(new String[]{})," & "))
//错误信息重定向到正常输出,减少一次io
.redirectErrorStream(true).start();
readStream(process.getInputStream());
//System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
} catch (IOException e) {
System.out.println("运行错误:" + e.getMessage());
e.printStackTrace();
}
});
}
}
public static void readStream(InputStream is) {
String line;
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(is, "gbk"));
StringBuilder CmdReturn = new StringBuilder();
line = input.readLine();
while (line != null) {
line = input.readLine();
CmdReturn.append(line);
}
//简单处理
System.out.println(CmdReturn.toString().replace("Windows IP 配置","\nWindows IP 配置"));
if(Objects.nonNull(input)){
input.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
type 1 count 1000 starts at 2021-08-16 23:35:48:111
submit done at 2021-08-16 23:35:48:194
jobs done at 2021-08-16 23:36:26:314
cost time: 38201 ms
type 2 count 1000 starts at 2021-08-16 23:36:26:316
submit done at 2021-08-16 23:36:26:323
jobs done at 2021-08-16 23:36:47:449
cost time: 21133 ms
type 3 count 1000 starts at 2021-08-16 23:36:47:450
submit done at 2021-08-16 23:36:47:473
jobs done at 2021-08-16 23:36:57:592
cost time: 10142 ms
Process finished with exit code 0
貌似慢在输出流的创建和读取这块,改成用文件试一下。
Process process;
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", path);
pb.redirectOutput(new File("c:/temp/out.txt."+i));
pb.redirectError(new File("c:/temp/error.txt."+i));
process = pb.start();
// 下面的注释掉
// readStream(process.getErrorStream());
// readStream(process.getInputStream());