设计模式以摆脱多线程环境中的标志/枚举

时间:2012-12-12 16:24:09

标签: java design-patterns coding-style

要修改的原始程序代码:

/ 定期调用此方法,它从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标志。这比(1)好,但不是很多,因为应用程序需要检查哪个命令是最后一个,以及它是否处于挂起模式并且正常运行。

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

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

3 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:1)

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

while true
  msg = getMsgFromQueue
  case msg 
    skipARow: skip();
    processARow: process();
    doSomethingElse: 

答案 2 :(得分:1)

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

图3.简单状态图:(来自here

Figure 3. Simple State Diagram

我个人使用FSM管理可应用于对象的操作(在本例中为Orders),管理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,但却是一个很好的工具 - 我已经多次使用它了,它很棒。