【问题标题】:Putting method calls into an ArrayList?将方法调用放入 ArrayList?
【发布时间】:2010-07-15 18:57:16
【问题描述】:

我在我的 Java 程序中添加了一个加载栏功能,我想知道是否可以设置一个需要完成的进程列表,以便它知道需要完成多少个进程。

例如,将它们保存为字符串?

ArrayList<String> processes = new ArrayList<String>();
processes.add("CSVWriter.createFileOfCompany(\"Random Company\");");
processes.add("FileConverter.convertCSVToXLS(classPath + 
    \"/Output/Random_Company.csv\");");

for (int i = 0; i < processes.size(); i++) {
    // run process
    // update loading bar
}

这些对我的程序来说不是真正的方法,但它们与我想要完成的非常相似。

我确定这不是最好的方法,但我想有一些方法来创建这样的列表,以便在运行它们之前知道有多少进程。我设置了一个系统来进一步分解这些过程并显示它们的进度,所以这个栏目前非常精确,但我必须为每个过程编号=/。

也许我只是错过了重点。创建进度条对我来说是全新的体验。

如果有任何关于进度条创建的好文章,请随时发送给我。请记住,我没有使用实际的基于摆动的 GUI。此栏全是 S.O.P 文本。

非常感谢,

贾斯蒂安·迈耶

【问题讨论】:

  • 您是否假设您的所有方法都将花费相同的时间来运行?
  • 我不希望他们这样做。我基本上想把这些方法分解成相等的块。如果有 5 个调用,它将被分成 5 个块。这些块中的每一个都将从方法中的循环接收信息以缓慢填充它们。想象成这样[///// | ///// | ///// | ///// | /////].......................[///// | ///// | //... | ..... | .....] 表示前两个流程已完成,流程 3 的 2/5 已完成。当然,它看起来更像:[////////////.............] 48%
  • 我创建它的方法并不像我想要的那样干净,所以我完全愿意接受更好的想法。
  • 我在下面从字面上回答了您的问题,但这确实不是实现脚本执行进度条的最佳方式。传统的方法是在每个语句之后手动报告您的进度。请记住,并非所有命令都花费相同的时间。
  • @Gunslinger47:手动报告是什么意思?像:“创建文件 [文件名]...完成”,“转换文件 [文件名]...完成”?那只是看起来不那么干净=/。试图让我的廉价 GUI 看起来尽可能友好。它基本上是一个点击即走的程序。

标签: java arrays methods progress-bar process


【解决方案1】:

希望在下一个 Java 版本中很快就会出现闭包,但在那之前,您可以使用匿名类来实现已知接口:

List<Runnable> jobs = new ArrayList<Runnable>();

jobs.add(new Runnable() {
    public void run() {
        CSVWriter.createFileOfCompany("Random Company");
    }
});

jobs.add(new Runnable() {
    public void run() {
        FileConverter.convertCSVToXLS(classPath + "/Output/Random_Company.csv");
    }
});

for (Runnable job : jobs) {
    job.run();
}

【讨论】:

  • 为什么不直接使用 Runnable 或 Callable(如果您需要能够抛出异常)而不是创建自己的“Job”接口。
  • 感谢您的编辑,@Sanity。我自己也身处其中。我最初决定使用自定义界面是为了更好地说明这个想法,但这只会增加噪音。
  • 是的,也许为了解释这个想法,自定义界面更好:-)
  • 哦!我记得在我的一本旧教科书中看到过这个概念。这么酷的主意:)。非常感谢帮忙。 +1 干净的帖子,+1 理智的编辑。
【解决方案2】:

这是我刚刚想到的一个方案:

interface WorkProcess
    void setWorkUnits(int units)
    void setArguments(Object obj1,...)
    void execute()

因此,您将所有任务封装在一个接口中,该接口按照经典命令模式执行execute;它还被告知(见下文)该工作可能需要多少工作。您可能需要某种机制将数据传递到这些任务中以供他们使用。

class WorkProcessFactory
    static WorkProcess makeWorkProcess()
    static int getTotalWorkUnitsAllocated()
    static synchronized int reportWorkDone(int units)
    static void addProgressListener(ProgressListener xxx)

当您有工作要做时,您要求工厂为您生产这些流程之一。这样做时,它会对工作单元进行估计并将其传递给它刚刚创建的 WorkProcess。它还记录了这些单元的总数,用于设置进度指示器的顶部。这样做的一个很酷的副作用是您不必等待所有作业都准备好:您可以在每次添加作业时增加进度报告的最大值,即使正在处理和新建作业;您的条形图将始终显示真实的比率。

您可以将工作流程塞入某种队列中。如果您的 WorkProcess 还实现了 Runnable 接口(这是一个好主意),就会想到 ExecutorService。无论您的执行队列机器支持什么,您都可以按顺序处理单个文件或并发处理这些作业。

WorkProcess 的execute() 方法基本上包装了run() 方法(或者可能反过来,因为 ExecutorService 需要一个 run() 方法,但我们的工作单元魔法在 execute() 中);但完成后,它会认真回拨reportWorkDone,并告知其工作价值的单位数量。收到这些报告后,工厂有一个已完成工作单元的更新值,它可以将其报告回侦听的 ProgressListener。这反过来又会更新 GUI 中的栏。

完成。 (我认为)。可能需要一些改进。

【讨论】:

    猜你喜欢
    • 2013-03-28
    • 2013-01-12
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2015-06-29
    • 1970-01-01
    • 2012-04-19
    相关资源
    最近更新 更多