我有工作线程,它需要根据另一个线程给出的命令(比如与用户交互的线程)执行各种任务。工作线程需要执行以下功能,
一个。一旦启动,工作线程需要等待用户线程给一个任务。
湾。一旦给定一个任务,工作线程需要继续执行该任务,除非另有说明。
C。在任何时间点,用户线程都可以要求工作线程停止(退出)、暂停、继续、暂停和等待另一个任务等。
在处理多线程程序时,我经常遇到这个用例,并且经常最终使用复杂的逻辑(很多 if/else、信号量信号/等待等)
所以我想知道这个用例是否有好的设计模式?
我有工作线程,它需要根据另一个线程给出的命令(比如与用户交互的线程)执行各种任务。工作线程需要执行以下功能,
一个。一旦启动,工作线程需要等待用户线程给一个任务。
湾。一旦给定一个任务,工作线程需要继续执行该任务,除非另有说明。
C。在任何时间点,用户线程都可以要求工作线程停止(退出)、暂停、继续、暂停和等待另一个任务等。
在处理多线程程序时,我经常遇到这个用例,并且经常最终使用复杂的逻辑(很多 if/else、信号量信号/等待等)
所以我想知道这个用例是否有好的设计模式?
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 会注意在线程上运行它们并在它们之间安全地传递消息。如果这看起来很有趣,请随时在邮件列表中查询更多信息。
在这里,我发布了一种方法的标题 - 它帮助我作为 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 {
我可能仍然想知道这是否是一个好的设计模式,但是通过使用状态机与否,如果你试图在一个地方(同时)让事情变得更简单,那么在另一个地方弄得更大的混乱并不难(健康)状况)。对我来说,中间道路是更高级别的编程,并且理所当然地认为所有这些超时,而不是可用性和死亡。
您的逻辑很可能很复杂,因为您试图让单个实体做太多工作(这会导致 O(N!) 复杂性)。
如果您将线程安全作为策略(线程安全/不安全队列、同步点、标志等)以及其他行为方面,那么工作人员和策略都将是简洁设计的紧凑可重用乐高积木。
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;