亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有限制的運行配置

有限制的運行配置

胡說叔叔 2022-11-30 10:55:10
我對如何繼續我的代碼有疑問。我的項目是一個在后臺一個一個地運行配置的工具。我想為運行配置的數量添加一個限制。例如,如果我有 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]此外,這configurations是一個列表configStructs。
查看完整描述

2 回答

?
神不在的星期二

TA貢獻1963條經驗 獲得超6個贊

抱歉vesii如果我不完全理解甚至誤解你的問題,但你的英語不是很好,即使在你發表評論后我也有問題,看看使用多線程的問題是什么。


無論如何,我建議你讓你的ConfigStruct類實現Runnable接口,這很容易,因為它已經有一個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。對于每個線程的不同處理時間,它看起來會更加不同。


更新:如果你想看到更多變化,只需在線程的睡眠時間中添加一個隨機元素并稍微擴展日志記錄:

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(先進先出)?


另請注意,如果您計算控制臺上活動(未完成)線程的數量,無論執行時間如何,它都不會超過 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 秒


查看完整回答
反對 回復 2022-11-30
?
郎朗坤

TA貢獻1921條經驗 獲得超9個贊

在我看來你正在尋找一個java.util.concurrent.CountDownLatch. 你給它一個數字(在你的情況下是 5)并等待一段時間讓它達到 0。谷歌會給你很多如何使用它的例子。



查看完整回答
反對 回復 2022-11-30
  • 2 回答
  • 0 關注
  • 106 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號