gpt4 book ai didi

java - 有限制的运行配置

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:58:19 25 4
gpt4 key购买 nike

我对如何继续我的代码有疑问。我的项目是一个在后台一个一个地运行配置的工具。我想为运行配置的数量添加一个限制。例如,如果我有 13 个配置,我想每次运行 5 个配置,那么顺序将是:

- Running 5 configurations
- All 5 configurations done running
- Running 5 configurations
- All 5 configurations done running
- Running 3 configurations
- All 3 configurations done running

目前的代码,工作如下:

public void runConfigurations(List<ConfigStruct> configurations) {
for (ConfigStruct configuration : configurations) {
try {
configuration.run();
} catch (ConfigurationException e) {
continue;
}
}
}

现在,它会一个一个地运行每个配置。 run 方法如下所示:

public void run() throws ConfigurationException {
StringBuffer runCmd = generateGalishFullCommand(GalishFlags.RUN);
try {
ExternalCommandExecutor.execute(runCmd, "Failed to run " + name, true, true);
} catch (IOException e) {
throw new ConfigurationException(e.getMessage());
}
}

execute 的签名如下所示:

public static String execute(final String cmd, final String error, final boolean runInBackground, final boolean retry) throws IOException;

起初,虽然我可以不在后台每 5 个配置运行最后一个配置,但它有问题。我不能不在后台执行每 5 个配置的最后一个配置,因为第一个配置可能最后完成。我该如何解决这个问题?

编辑:

当我打印配置时,它看起来如下:

[com.configStructs@3f15dbec, com.configStructs@31d2327e]

此外,configurationsconfigStructs 的列表。

最佳答案

抱歉 vesii 如果我没有完全理解甚至误解你的问题,但你的英语不是很好,即使在你的评论之后我也有问题,看看使用多线程的问题是什么.

无论如何,我建议你让你的 ConfigStruct 类实现 Runnable 接口(interface),这很容易,因为它已经有一个 run() 方法.您只需要摆脱抛出已检查的异常,因此我进一步建议将 ConfigurationException 设为 RuntimeException,您不必在方法签名中声明它。

很遗憾,您没有提供完整的 MCVE ,只有代码片段。所以我必须弥补其余部分才能编译和运行您的代码。我只是添加了一些简单的助手/虚拟类。我的解决方案如下所示:

package de.scrum_master.app;

public enum GalishFlags {
RUN
}
package de.scrum_master.app;

public class ConfigurationException extends RuntimeException {
private static final long serialVersionUID = 1L;

public ConfigurationException(String message, Throwable cause) {
super(message, cause);
}
}
package de.scrum_master.app;

import java.io.IOException;

public class ExternalCommandExecutor {
public static String execute(final String cmd, final String error, final boolean runInBackground, final boolean retry) throws IOException {
System.out.println("Executing external command: " + cmd);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return cmd;
}
}

如您所见,命令执行器在将内容打印到控制台后等待 100 毫秒。如果您希望程序运行得更慢或什至随机化以模拟需要不同时间完成的命令,您也可以将其更改为 1000 毫秒。

现在我们需要一个小的驱动程序应用程序,我们可以在其中生成配置并运行它们。解决永远不会同时运行超过 5 个线程的问题的关键是通过 Executors.newFixedThreadPool(5) 创建一个固定线程池。其余的应该很容易理解。

package de.scrum_master.app;

import java.io.IOException;

public class ConfigStruct implements Runnable {
private String name;

public ConfigStruct(String name) {
this.name = name;
}

@Override
public void run() {
StringBuffer runCmd = generateGalishFullCommand(GalishFlags.RUN);
try {
ExternalCommandExecutor.execute(runCmd.toString(), "Failed to run " + name, true, true);
} catch (IOException e) {
throw new ConfigurationException(e.getMessage(), e);
}
}

private StringBuffer generateGalishFullCommand(GalishFlags run) {
return new StringBuffer("Galish full command for ConfigStruct '" + name + "'");
}
}
package de.scrum_master.app;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Application {
public void runConfigurations(List<ConfigStruct> configurations) {
for (ConfigStruct configuration : configurations) {
try {
configuration.run();
} catch (ConfigurationException e) {
continue;
}
}
}

public void runConfigurationsThreaded(List<ConfigStruct> configurations) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (ConfigStruct configuration : configurations)
executorService.execute(configuration);
executorService.shutdown();
try {
executorService.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
List<ConfigStruct> configurations = new ArrayList<>();
for (int i = 1; i <= 13; i++)
configurations.add(new ConfigStruct("Configuration " + i));

long startTime = System.currentTimeMillis();
new Application().runConfigurations(configurations);
System.out.println("Total time (1 thread) = " + (System.currentTimeMillis() - startTime) + " ms");
System.out.println();

startTime = System.currentTimeMillis();
new Application().runConfigurationsThreaded(configurations);
System.out.println("Total time (5 threads) = " + (System.currentTimeMillis() - startTime) + " ms");
}
}

控制台日志看起来像这样:

Executing external command: Galish full command for ConfigStruct 'Configuration 1'
Executing external command: Galish full command for ConfigStruct 'Configuration 2'
Executing external command: Galish full command for ConfigStruct 'Configuration 3'
Executing external command: Galish full command for ConfigStruct 'Configuration 4'
Executing external command: Galish full command for ConfigStruct 'Configuration 5'
Executing external command: Galish full command for ConfigStruct 'Configuration 6'
Executing external command: Galish full command for ConfigStruct 'Configuration 7'
Executing external command: Galish full command for ConfigStruct 'Configuration 8'
Executing external command: Galish full command for ConfigStruct 'Configuration 9'
Executing external command: Galish full command for ConfigStruct 'Configuration 10'
Executing external command: Galish full command for ConfigStruct 'Configuration 11'
Executing external command: Galish full command for ConfigStruct 'Configuration 12'
Executing external command: Galish full command for ConfigStruct 'Configuration 13'
Total time (1 thread) = 1374 ms

Executing external command: Galish full command for ConfigStruct 'Configuration 1'
Executing external command: Galish full command for ConfigStruct 'Configuration 2'
Executing external command: Galish full command for ConfigStruct 'Configuration 3'
Executing external command: Galish full command for ConfigStruct 'Configuration 4'
Executing external command: Galish full command for ConfigStruct 'Configuration 5'
Executing external command: Galish full command for ConfigStruct 'Configuration 6'
Executing external command: Galish full command for ConfigStruct 'Configuration 7'
Executing external command: Galish full command for ConfigStruct 'Configuration 8'
Executing external command: Galish full command for ConfigStruct 'Configuration 10'
Executing external command: Galish full command for ConfigStruct 'Configuration 9'
Executing external command: Galish full command for ConfigStruct 'Configuration 11'
Executing external command: Galish full command for ConfigStruct 'Configuration 13'
Executing external command: Galish full command for ConfigStruct 'Configuration 12'
Total time (5 threads) = 344 ms

请注意:

  • 在单线程循环中运行时,运行时间 > 1,300 毫秒(13 x 100 毫秒)。
  • 在具有 5 个线程的线程池中运行时,运行时间 > 300 毫秒(3 x 100 毫秒)- 根据同时处理 5 个配置的要求,这正是您所期望的。
  • 由于多线程,日志输出不是直接从 1 到 13,而是有点不同,这里最后是 8、10、9、11、13、12。对于每个线程的不同处理时间,它看起来会更加不同。

更新:如果您想看到更多变化,只需在线程的 hibernate 时间中添加一个随机元素并稍微延长日志记录:

package de.scrum_master.app;

import java.io.IOException;
import java.util.Random;

public class ExternalCommandExecutor {
private static final Random RANDOM = new Random();

public static String execute(final String cmd, final String error, final boolean runInBackground, final boolean retry) throws IOException {
long sleepTime = 100 + 100 * (RANDOM.nextInt(3));
System.out.println("Executing external command: " + cmd + ", sleeping for " + sleepTime + " ms");
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finished execution: " + cmd);
return cmd;
}
}

然后控制台日志可能如下所示:

Executing external command: Galish full command for ConfigStruct 'Configuration 1', sleeping for 300 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 1'
Executing external command: Galish full command for ConfigStruct 'Configuration 2', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 2'
Executing external command: Galish full command for ConfigStruct 'Configuration 3', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 3'
Executing external command: Galish full command for ConfigStruct 'Configuration 4', sleeping for 300 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 4'
Executing external command: Galish full command for ConfigStruct 'Configuration 5', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 5'
Executing external command: Galish full command for ConfigStruct 'Configuration 6', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 6'
Executing external command: Galish full command for ConfigStruct 'Configuration 7', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 7'
Executing external command: Galish full command for ConfigStruct 'Configuration 8', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 8'
Executing external command: Galish full command for ConfigStruct 'Configuration 9', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 9'
Executing external command: Galish full command for ConfigStruct 'Configuration 10', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 10'
Executing external command: Galish full command for ConfigStruct 'Configuration 11', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 11'
Executing external command: Galish full command for ConfigStruct 'Configuration 12', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 12'
Executing external command: Galish full command for ConfigStruct 'Configuration 13', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 13'
Total time (1 thread) = 2314 ms

Executing external command: Galish full command for ConfigStruct 'Configuration 1', sleeping for 300 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 2', sleeping for 300 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 3', sleeping for 200 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 5', sleeping for 300 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 4', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 4'
Executing external command: Galish full command for ConfigStruct 'Configuration 6', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 3'
Executing external command: Galish full command for ConfigStruct 'Configuration 7', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 1'
Finished execution: Galish full command for ConfigStruct 'Configuration 2'
Executing external command: Galish full command for ConfigStruct 'Configuration 8', sleeping for 200 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 9', sleeping for 100 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 5'
Executing external command: Galish full command for ConfigStruct 'Configuration 10', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 6'
Executing external command: Galish full command for ConfigStruct 'Configuration 11', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 9'
Finished execution: Galish full command for ConfigStruct 'Configuration 7'
Executing external command: Galish full command for ConfigStruct 'Configuration 12', sleeping for 200 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 13', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 8'
Finished execution: Galish full command for ConfigStruct 'Configuration 10'
Finished execution: Galish full command for ConfigStruct 'Configuration 11'
Finished execution: Galish full command for ConfigStruct 'Configuration 13'
Finished execution: Galish full command for ConfigStruct 'Configuration 12'
Total time (5 threads) = 609 ms

看看在单线程模式下如何仍然一切都是 FIFO(先进先出)?

另请注意,如果您计算控制台上 Activity (未完成)线程的数量,无论执行时间如何,它都不会超过 5。最后 5 个线程结束。而且总执行时间仍然明显小于单线程情况。


更新 2: 最后但同样重要的是,如果将主循环中的元素数量从 13 增加到更大的数字,比如 100,您会注意到最后的总执行时间多线程解决方案的大约是单线程解决方案的 1/5(或通常 1 除以固定线程池中的线程数)。这是因为线程除了等待并打印到控制台外没有做太多其他事情。如果他们实际上做了更多的工作,例如繁重的计算或大量的 I/O,那么改进将不那么显着,但仍然很重要。

我对 100 个配置元素的尝试产生了以下输出(缩写):

Executing external command: Galish full command for ConfigStruct 'Configuration 1', sleeping for 300 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 1'
(...)
Executing external command: Galish full command for ConfigStruct 'Configuration 100', sleeping for 300 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 100'
Total time (1 thread) = 20355 ms

Executing external command: Galish full command for ConfigStruct 'Configuration 2', sleeping for 100 ms
Executing external command: Galish full command for ConfigStruct 'Configuration 1', sleeping for 300 ms
(...)
Executing external command: Galish full command for ConfigStruct 'Configuration 100', sleeping for 200 ms
Finished execution: Galish full command for ConfigStruct 'Configuration 99'
Finished execution: Galish full command for ConfigStruct 'Configuration 93'
Finished execution: Galish full command for ConfigStruct 'Configuration 94'
Finished execution: Galish full command for ConfigStruct 'Configuration 95'
Finished execution: Galish full command for ConfigStruct 'Configuration 100'
Total time (5 threads) = 3923 ms

看到了吗? ~20 秒/5 = ~4 秒

关于java - 有限制的运行配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56155737/

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