首页 > 解决方案 > 具有多个连接但只有一个线程的 ServerSocket

问题描述

我正在尝试为单线程物理产品编写模拟器。它接受一个长期连接,而任何其他连接都会收到一条错误消息(在同一个线程中)。

我知道我可以将 java.net 与两个线程一起使用:

但是我怎么能用一个线程来做到这一点,所以它的行为更像物理产品(即重复尝试连接会使线程无法处理第一个连接)?

尽量不使用第三方库,但如果这是唯一的选择,可以这样做。

谢谢!

标签: javaserversocket

解决方案


不幸的是,接受传入连接的阻塞方法是常见java.net.ServerSocket的也是唯一的功能。java.nio.channels.ServerSocketChannel但是,该java.nio包具有许多其他类和方法,可通过多路复用打开的通道在单个线程中处理 I/O 操作。

这种方法仍然会强制使用专用线程来接受ServerSocketChannel,但您可以在单个线程中处理每个接受的连接。

相比之下,该ServerSocket方法需要为每个新连接一个新线程。
假设您使用 a 连接 100 个客户端,ServerSocket那么您最终将获得 101 个线程。使用 aServerSocketChannel您最终可能只使用 2 个线程。

仍然编程通常是在复杂性/灵活性和性能之间进行权衡。所以记住这一点。

我能想到的一个可能的解决方案可能如下所示:

public static void main( String[] args ) throws IOException
{
  int portNr = 8080;

  ExecutorService es = Executors.newSingleThreadExecutor();
  ChannelHandler ch = new ChannelHandler(); 
  es.execute( ch );

  // Starting server:
  ServerSocketChannel serv = ServerSocketChannel.open();
  // Bind socket to Port
  serv.socket().bind(new InetSocketAddress(portNr));

  while( serverAlive ) 
  {
    ch.addChannel(serv.accept());
  }
  serv.close();
}

您实际处理新添加的方式SocketChannel取决于您的应用程序。方法也是如此ChannelHandler#addChannel


推荐阅读