我有工作线程需要根据另一个线程(比如与用户交互的线程)给出的命令执行各种任务。工作线程需要执行以下功能,
一个。一旦启动,工作线程需要等待用户线程给出任务 湾一旦给出任务,工作者线程需要继续执行任务,除非被告知不这样做 C。在任何时间点,用户线程都可以要求工作线程停止(退出),暂停,继续,暂停并等待另一个任务等。
我在处理多线程程序时多次遇到这个用例,并且经常最终使用复杂的逻辑(很多if / elses,信号量信号/等待等)。
所以我想知道这个用例是否有好的设计模式?
答案 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 {
我可能仍然想知道这是不是一个好的设计模式,但是通过使用状态机,如果你试图在一个地方(同时)保持简单,那么它就不那么难了不同的地方(条件)。对我来说,中间道路是一个更高层次的编程,并且理所当然,所有这些超时,而不是可用性和死亡。