2012-11-13 34 views
0

我有工作线程需要根据另一个线程(例如与用户交互的线程)给出的命令执行各种任务。工作者线程需要执行以下功能:处理线程之间的状态变化

a。一旦开始,工作线程需要等待用户线程发出任务。 b。一旦给出任务,工作线程需要继续执行任务,除非被告知不这样做。
c。在任何时候,用户线程都可以要求工作线程停止(退出),暂停,继续,暂停和等待另一个任务等。

我在使用多线程程序时多次遇到此用例并通常最终使用复杂的逻辑(很多if/elses,信号量信号/等待等)

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

+0

这实在是一个非常不寻常的情况,并不典型。一般来说,如果你需要做的工作,你就可以做到。不得不停下来,暂停,继续或等待是非常不寻常的。我已经编写了十多年的多线程程序,并且从未做过任何这些事情。 (除了等待工作时,几乎没有任何事情可做,但这是基本工作调度机制的一部分,而不是额外的事情。) –

+0

@DavidSchwartz:我在应用程序级别处理用例请求可能出现的这些用例以任何顺序。一个很好的例子是相机应用程序:启动应用程序,开始预览,暂停预览,拍照,锁定屏幕,退出应用程序等。 –

+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; 
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%防弹(因为我希望把重点放在展示的一般原则),而且它也没有在阿卡写这样的事情的唯一途径。重要的部分是你不明确地管理线程,你只管理你的actor,Akka会小心地在线程上运行它们并在它们之间安全地传递消息。如果这看起来有趣,请随时查询有关mailing list的更多信息。

0

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

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

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 { 

我可能还是想知道,如果这是一个很好的设计模式,但是通过使用状态机或而不是,如果你试图在一个地方保持简单的话(while),那么在一个不同的地方(条件)就不难得到更大的混乱。对我而言,这是一个更高层次的程序,并且理所当然,所有这些超时,而不是可用性和死亡。

相关问题