【问题标题】:How is it possible to write event based single threaded programs?如何编写基于事件的单线程程序?
【发布时间】:2019-07-15 03:13:01
【问题描述】:

我对线程的了解非常有限。我碰巧是一个可以编写多线程程序的人,但只是通过复制粘贴并在互联网上找到我的问题的答案。但我最终决定学习一点并发,买了《Java Concurrency in Practice》一书。阅读几页后,我相信我会从这本书中学到很多东西。

也许我有点不耐烦,但我无法抗拒提出这个问题的诱惑。它让我在 Stack Overflow 上创建了一个帐户。我不确定我能否正确表达问题,所以我会尝试用一个例子来解释我的问题。

如果我必须用 Java 等语言编写一个(编码极不专业的)点对点聊天客户端,我将在客户端之间启动一个套接字连接并使其保持活动状态,因为消息可以随时到达。我可以想象的解决方案是在一个新线程中打开一个套接字连接并连续运行一个while循环以保持线程处于活动状态,因为一旦run返回,线程就会死亡。出于某种原因,我无法在单线程程序中想象类似的聊天客户端。如果你只有一个线程,你怎么能一直“等待”直到消息到达。这不会阻止整个程序的执行吗?

要解决这样的问题,有什么替代连续的while 循环的方法?

【问题讨论】:

  • 如果您的聊天应用程序的工作方式是一侧始终是发送者,另一侧始终是接收者,那么在一定程度上,可以使用单线程来实现这一点。否则,您将始终有一个专用线程来完成连接工作(或者 API 会为您完成)。
  • 简而言之:是的。在Socket 的输入流块上调用read。这就是为什么这通常使用专用线程来完成。您可以使用available() 来检查数据是否存在,以免一直调用read,但通常您需要一个线程或像 Mina 这样的库来处理这个问题。
  • 有异步网络之类的东西。没有线程需要等待 I/O 操作结束。相反,一旦操作完成,任务(类型为`Runnable`)就会准备好执行。它处理事件,并可以启动另一个 I/O 操作。
  • 虽然我理解这个问题,但编写线程来处理你的聊天客户端可能比单线程容易得多。继续四处寻找对您有意义的好线程教程。您不需要任何真正花哨的东西,因此基本教程应该会有所帮助。祝你好运!
  • 目前我真的不需要编写聊天客户端。自从线程被介绍给我以来,我就一直在想这个问题。我正在阅读 Java Concurrency in Practice 一书,到目前为止一切似乎都很简单。无论如何,我很感激你的建议。感谢大家抽出宝贵的时间发布您宝贵的 cmets 和答案。

标签: java multithreading concurrency


【解决方案1】:

如果你只有一个线程,你怎么能一直“等待”直到消息到达。

一种可能性是让“并行”发生在您的应用程序“外部”。想象一下餐厅里的服务员。只有一个人。他从一位顾客走到另一位顾客,然后写下订单。不时地,他走到柜台前,点菜,拿起厨师留给他的任何东西。只有一个人,四处走动,做“单一任务”的工作。但最终,整个系统仍然有多个演员(客人、服务员、厨师、酒吧外准备饮料的人)。因此,服务员可以被视为“单线程”,但最终,整个系统都不是“餐厅”。

一些 IT 架构“模仿”了这一点,例如围绕“非阻塞”IO 的概念。这就是 node.js 的工作方式。它本质上是单线程的,但执行异步 IO(有关详细信息,请参阅here)。你也可以用 Java 做类似的事情。

另一方面,当您了解并发时,您仍然想了解“真正的”多线程、它的含义以及如何编写代码来“使用”该概念。

【讨论】:

  • 请原谅我的无知,但我无法将服务员类比用于单线程聊天应用程序问题。服务员做什么(添加到订单列表中)可以理解为 Node 架构中的事件循环(否?)。当服务员去点菜时,厨师不必等他回来准备食物。他可以简单地从订单队列中取出一个。但是,很明显,我们确实需要至少两个人(服务员和厨师)来经营这样一家餐厅。您能否解释一下这个类比与聊天客户端问题有何关系?
  • 因此,一旦中断“等待消息”的任务完成,我们就会继续“等待消息”,直到发生另一个中断(可能通过布尔标志发出信号)来处理另一个任务。你说的对吗?
  • “它可以稍后返回并检查输入是否在等待它。”,如果我的程序正忙于处理其他重要的事情,谁将负责在输入到达时注册?我可以准确地告诉你我现在脑子里发生的事情。我把输入想象成一个网球,而聊天应用程序想象成一个应该接住它的人。如果接球手忙着说,系鞋带,球不会直接打到他反弹回来吗?
  • @ViplavKumar 当然,如果您有一个线程,并且该线程正忙于其他事情,那么您的程序会“冻结”。您经常会看到,当人们不了解他们应该在 Swing 事件调度程序线程上做任何实际工作时。该线程仅负责“传递” UI 事件,例如按钮单击……当人们现在在该线程的上下文中执行计算密集型事情时……然后整个 UI 冻结。这就是重点:这种单线程架构非常依赖于您遵循某些模式。
  • 我不会假装我完全理解了一切,但你的回答确实有帮助。接受答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多