0

原程序代码修改:

/这个方法被定期调用,它从 db 中获取数据,对其执行一些操作,并将结果放入一个文件中,该文件在所有处理结束时通过 ftp 发送/

void pullData(){
    while(!stopped){
        rows= getRowsFromDb();

        for (row: rows){
            newRow= process(row);
            rowsContainer.add(newRow)
        }

        writeToFile(rowsContainer);
        sendFileSomewhere();
    }
}

现在必须修改此代码以允许向其发出以下命令:仅处理 1 行;跳过 1 行(稍后会有更多命令)。为此,应用程序处于挂起模式,并且在获得我上面概述的 2 个命令之一之前,它不会处理行。此外,它可以从暂停模式恢复,然后恢复正常处理。

问题不是如何做到这一点,而是什么是正确的方法。

(1) 有人建议为每个操作设置布尔标志。这是一个非常糟糕的主意。我建议人们出于多种原因避免使用标志(有些可能已经讨论过堆栈溢出)。

(2) 另一个想法是对 isSuspended 使用 bool 标志,对命令使用 enums。这比(1)好,但不是很多,因为应用程序需要检查哪个命令是最后一个命令,以及它是否处于暂停模式并采取相应的行动。

(3) 我正在考虑拆分应用程序并使用策略模式。每个命令都会在应用程序中获得它自己的方法。这有点复杂,但对我来说似乎更干净。

你有什么建议(你不需要从我列出的选项中选择,我想听听你是如何处理类似情况的)?

4

3 回答 3

2

我会使用ExecutorService来完成类似的任务

private Future lastTask = null;

// only run one task at a time.
if (lastTask != null) lastTask.cancel(true);

lastTask = executorService.submit(new ProcessOnRowRunnable());
// or
lastTask = executorService.submit(new ProcessPendingRowsAndStopRunnable());
// or
lastTask = executorService.submit(new ProcessAllRowsUntilCancelledRunnable())

// later
future.cancel(true);

注意:您的循环必须尊重中断,否则它们不会因为线程被中断而停止。您可以使用

while(conditions && !Thread.curentThread().isInterrupted()) {
     // do work
}
于 2012-12-12T16:30:42.653 回答
1

我认为您需要一个消息传递 ITC:

while true
  msg = getMsgFromQueue
  case msg 
    skipARow: skip();
    processARow: process();
    doSomethingElse: 
于 2012-12-12T16:52:56.573 回答
1

在使用有限状态机(或基于枚举的简单状态驱动的子集)之前,我已经做过很多次了——最大的好处是你可以验证你的 FSM 并保持一些可管理的东西,而不会受到大量的标志问题

图 3. 简单状态图:(来自此处

图 3. 简单状态图

我个人使用 FSM 管理可应用于对象(在本例中为订单)的操作,管理 RFC-822 电子邮件消息的解析,控制硬件;

状态驱动循环的一个非常简单但实用的示例:

state = S_Starting;
while(state != S_Finished){

    switch (state){
        case S_Starting:
             // do something 
             state = S_Running;
             break;

        case S_Running
             rows= getRowsFromDb();

             for (row: rows){
                  newRow= process(row);
                  rowsContainer.add(newRow)
             }
             state = S_HandleReceipt;

             break;

         case S_HandleReceipt:
             writeToFile(rowsContainer);
             sendFileSomewhere();

         case S_Paused:
             if (some_other_test){
                 state = S_Running;
             }
             break;
    }
    if (some_test_for_finished) {
        state = S_Finished;
    } else if (some_test_for_pause) {
                  state = S_Paused;
    }
}

参考:

遗憾的是,C# Hierarchical State Machine Stateless还没有移植到 Java,但它是一个出色的工具——我已经使用过很多次了,它很棒。

于 2012-12-12T17:19:32.727 回答