0

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

一个。一旦启动,工作线程需要等待用户线程给一个任务。
湾。一旦给定一个任务,工作线程需要继续执行该任务,除非另有说明。
C。在任何时间点,用户线程都可以要求工作线程停止(退出)、暂停、继续、暂停和等待另一个任务等。

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

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

4

4 回答 4

1

Actor 模型可能非常适合这些情况。我正在研究Akka 工具包,您可以在文档中阅读有关使用演员构建软件的更多信息。为了让您对您描述的工作实体的外观有一些印象,请考虑以下代码(用 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
}

然后,您可以通过向它发送消息来与这样的状态机交互:

// 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 会注意在线程上运行它们并在它们之间安全地传递消息。如果这看起来很有趣,请随时在邮件列表中查询更多信息。

于 2012-11-13T16:09:07.763 回答
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 {

我可能仍然想知道这是否是一个好的设计模式,但是通过使用状态机与否,如果你试图在一个地方(同时)让事情变得更简单,那么在另一个地方弄得更大的混乱并不难(健康)状况)。对我来说,中间道路是更高级别的编程,并且理所当然地认为所有这些超时,而不是可用性和死亡。

于 2012-11-25T02:12:05.567 回答
0

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

如果您将线程安全作为策略(线程安全/不安全队列、同步点、标志等)以及其他行为方面,那么工作人员和策略都将是简洁设计的紧凑可重用乐高积木。

于 2012-11-15T09:46:30.407 回答
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;
于 2012-11-13T01:13:56.547 回答