处理线程之间的状态更改

时间:2012-11-13 01:06:58

标签: multithreading oop design-patterns concurrency

我有工作线程需要根据另一个线程(比如与用户交互的线程)给出的命令执行各种任务。工作线程需要执行以下功能,

一个。一旦启动,工作线程需要等待用户线程给出任务 湾一旦给出任务,工作者线程需要继续执行任务,除非被告知不这样做 C。在任何时间点,用户线程都可以要求工作线程停止(退出),暂停,继续,暂停并等待另一个任务等。

我在处理多线程程序时多次遇到这个用例,并且经常最终使用复杂的逻辑(很多if / elses,信号量信号/等待等)。

所以我想知道这个用例是否有好的设计模式?

4 个答案:

答案 0 :(得分:1)

actor model可能适合这些情况。我正在研究Akka toolkit,您可以阅读有关使用documentation中的演员构建软件的更多信息。为了让您对您描述的工作者实体的外观有所了解,请考虑以下代码(用Scala编写,但应该是描述性的):

trait State
case object Idle extends State   // marker object for the no-work state
case object Active extends State // marker object for when there is work to do
case object Paused extends State // marker for when work is known but paused

class Worker extends Actor extends FSM[State, Option[Work]] {
  startWith(Idle, None) // start out with no work to do
  when(Idle) {
    case Event(DoWork(workPackage), _) =>
      self ! KickMe // message sent to this actor to make it perform some work
      goto(Active) using Some(workPackage)
  }
  when(Active) {
    case Event(KickMe, Some(work)) =>
      execute(work)
      self ! KickMe // this keeps the work going until told otherwise
      stay()
    case Event(Pause, _) =>
      goto(Paused)
  }
  when(Paused) {
    // KickMe messages are ignored in this state, leading to a pause
    case Event(Resume, _) =>
      self ! KickMe
      goto(Active)
  }
  whenUnhandled { // these cases apply in all three states
    case Event(Stop, _) =>
      stop()
    case Event(DropIt, _) =>
      goto(Idle) using None // zero out the current work package
  }

  def execute(work: Work) = ... // whatever there is to do
}

然后,您可以通过发送消息与state machine进行互动:

// initialize Akka
val system = ActorSystem("demo") 
// instantiate the actor, returning an ActorRef
val workerRef = system.actorOf(Props[Worker], name = "Fred")
// send the first work package to get it going
workerRef ! DoWork(new MyWork(...)) // whatever the work package
... // after some time
workerRef ! Pause
... // and then even later maybe
workerRef ! Resume
... // and finally
workerRef ! Stop

上面的实现不是100%防弹(因为我想专注于演示一般原则),而且它也不是在Akka中写这样的东西的唯一方法。重要的是你没有明确地管理线程,你只管理你的actor,Akka会注意在线程上运行它们并在它们之间安全地传递消息。如果这看起来很有趣,请随时查询有关mailing list的更多信息。

答案 1 :(得分:0)

object thisLock;
bool paused;
bool exit;

void YourThread() {

    while (true)
    {

        lock (thisLock)
        {

            if (exit) return;

            while (paused)
                Monitor.Wait(thisLock);


        }

        //do some work
        //process one item
        //whatever

    }

}

暂停 -

paused = true;

取消暂停 -

lock (thisLock)
{
    paused = false;
    Monitor.Pulse(thisLock);
}

退出

exit = true;

答案 2 :(得分:0)

你的逻辑很可能很复杂,因为你试图让一个实体做太多工作(导致O(N!)复杂性)。

如果您将线程安全作为策略(线程安全/不安全队列,同步点,标志等)以及其他行为方面,那么工作者和策略将是紧凑的可重用Lego块的干净设计。

答案 3 :(得分:0)

这里我发布了一个方法的标题 - 它帮助我作为while循环的前提条件:

private static final boolean conditionMet (
    final boolean isEventDispatchThread    
    , final List<AWTEvent> pendingEvents
    , final AtomicBoolean isDefaultEventQueue
    , final AtomicBoolean isEventQueueChanging
    , final AtomicReference<DispatchableEventQueue> newEventQueue
    , final AtomicReference<ProgressMonitor> processMessageBlocking
    , final AtomicInteger actionsRemaining
    , final AtomicBoolean interruptAction
    , final AtomicReference<Tuple2<IAction, Throwable>> throwableWasThrownFromChain        
    , final ConcurrentHashMap<IAction, Boolean> valuesReadyToBeSetFromEDT
    , final ConcurrentHashMap<IAction, Boolean> valuesWasSetFromEDT
    , final ConcurrentHashMap<IAction, Boolean> onSwingReadyToBeRunFromEDT
    , final ConcurrentHashMap<IAction, Boolean> onSwingWasActuallyRunFromEDT
    , final FlexReference<Map<String, Object>> remoteRef        
) throws InterruptedException {

我可能仍然想知道这是不是一个好的设计模式,但是通过使用状态机,如果你试图在一个地方(同时)保持简单,那么它就不那么难了不同的地方(条件)。对我来说,中间道路是一个更高层次的编程,并且理所当然,所有这些超时,而不是可用性和死亡。