首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用阻塞I/O的Java线程池服务器

使用阻塞I/O的Java线程池服务器
EN

Stack Overflow用户
提问于 2014-05-30 12:07:26
回答 1查看 1.7K关注 0票数 3

我用Java实现了一个服务器,当从某个客户端接收数据时,它只是将数据转发给所有其他客户端(包括发送方)。我对我的OO设计很满意,我把所有的套接字封装在提供‘回调’的类中。当一些数据准备好(或者当套接字关闭时)会调用这些--使用这个设计,我可以很容易地实现一个简单的TLV协议来原子地发送数据包:回调在接收到完整的数据包之前是不会被调用的。

现在,我使用java.io包阻止对套接字流的I/O调用(并通过这些回调使它们看起来‘异步’)。因此,我在套接字包装器类中使用线程:当打开套接字时,该函数返回一个Runnable实现,在运行时,该实现将对InputStream进行阻塞调用,缓冲数据,并最终调用回调。

=>在客户端应用程序中,我只是在一个Thread实例中启动这个Runnable,因为它只是一个线程。

在我的服务器中,我将创建新套接字(即接受新客户端时)获得的所有=>实现提交到ThreadPoolExecutor中。(FYI:套接字的回调只需put BlockingQueue中接收的数据包即可。一个单独的(非池化的) "dispatcher“Thread实例经常从这个队列中take数据包,并将它们写入当前连接到服务器的所有套接字。

问题:--这一切都很好,但是我不确定如何使用ThreadPoolExecutor,因为提交的Runnable实例几乎总是阻塞的。ThreadPoolExecutor会对此做出反应吗?或者池线程会简单地阻塞吗?因为,如果所有池线程在执行它们的Runnable和next时都处于阻塞状态,那么将提交一个新的Runnable,然后呢?暂停新的Runnable?这并不好,因为这样,新连接的客户端将没有响应,直到一些老客户端断开连接。相反,如果线程池选择生成一个新线程来处理Runnable,那么我实际上得到了一个每个客户端线程的场景。

我希望线程池“抢占”阻塞线程,并使用它们来处理其他套接字,就像一个暂停I/O绑定进程并在I/O完成之前不调度进程的操作系统。这是可能的吗,还是我必须用nio重写所有东西才能做到这一点?(如果需要nio,你能指出我应该从哪里开始阅读吗?)

提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-30 17:45:43

关于ThreadPoolExecutor:视情况而定。Executors.newCachedThreadPool()只会为新的Runnable创建新的线程。也见这个问题和公认的答案。但最终您将得到一个每个客户端线程的场景。

Nio防止了每个客户端线程的场景(如果有许多客户端发送相对较小的消息,中间有停顿,请参见(这篇文章的摘要)),我建议不要尝试构建自己的nio克隆。

从根本上实现nio并不容易,一个教程可以找到这里。使用nio服务器(如奈蒂 )可能更容易一些。

另一种选择是使用一种技术来处理许多发送和接收小消息的客户端。学习和设置需要一些时间,但我设法让Tomcat WebSockets服务器与码头WebSocket客户端进行了相当快的对话。使用这一技术进行重写可能会减少工作量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23954253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档