2012-11-13 97 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),那麼在一個不同的地方(條件)就不難得到更大的混亂。對我而言,這是一個更高層次的程序,並且理所當然,所有這些超時,而不是可用性和死亡。

相關問題