0

別のスレッド (ユーザーと対話するスレッドなど) によって与えられたコマンドに基づいてさまざまなタスクを実行する必要があるワーカー スレッドがあります。ワーカー スレッドは、次の機能を実行する必要があります。

を。開始すると、ワーカー スレッドは、ユーザー スレッドがタスクを与えるのを待つ必要があります。
b. タスクが与えられると、ワーカー スレッドは、特に指示がない限り、タスクを実行し続ける必要があります。
c. いつでも、ユーザー スレッドはワーカー スレッドに停止 (終了)、一時停止、続行、一時停止、および別のタスクの待機などを要求できます。

マルチスレッドプログラムで作業しているときに、このユースケースに何度も出くわし、多くの場合、複雑なロジック (多数の if/else、セマフォシグナル/待機など) を使用することになります。

このユースケースに適した設計パターンがあるかどうか疑問に思っていますか?

4

4 に答える 4

1

アクター モデルは、このような状況に適している可能性があります。私は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 でこのようなものを記述する唯一の方法でもありません。重要な点は、スレッドを明示的に管理するのではなく、アクターのみを管理することです。Akka はスレッド上でアクターを実行し、アクター間でメッセージを安全に受け渡します。これが興味深いと思われる場合は、お気軽にメーリング リストで詳細をお問い合わせください。

于 2012-11-13T16:09:07.763 に答える
0

単一のエンティティに多くの作業をさせようとしているため、ロジックが複雑になる可能性があります (結果として O(N!) の複雑さが生じます)。

スレッド セーフをポリシー (スレッド セーフ/アンセーフ キュー、同期ポイント、フラグなど) に加えて、他の動作面と組み合わせると、ワーカーとポリシーの両方がクリーンなデザインの再利用可能なコンパクトなレゴ ブロックになります。

于 2012-11-15T09:46:30.407 に答える
0

ここでは、1 つのメソッドのヘッダーを投稿します。これは、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
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 に答える