使用Executors.newFixedThreadPool的异步Java NIO需要帮助
嘿,伙计们,我正在开发一个服务器程序,它可以很好地扩展并服务于潜在的数千个客户端。问题是,我觉得ApacheMina太重了,所以我决定不使用它,而是编写了自己的客户机侦听器。我从来没有真正用Java执行过异步套接字操作(C#使这变得容易多了,但我真的更喜欢用Java编写这个项目,因为除了套接字读取之外,我对它在所有方面都比较熟悉),所以试图理解如何正确使用线程池对我来说很困难。我使用ApacheMina文档了解应该如何做。我有两个问题:使用Executors.newFixedThreadPool的异步Java NIO需要帮助,java,sockets,buffer,threadpool,Java,Sockets,Buffer,Threadpool,嘿,伙计们,我正在开发一个服务器程序,它可以很好地扩展并服务于潜在的数千个客户端。问题是,我觉得ApacheMina太重了,所以我决定不使用它,而是编写了自己的客户机侦听器。我从来没有真正用Java执行过异步套接字操作(C#使这变得容易多了,但我真的更喜欢用Java编写这个项目,因为除了套接字读取之外,我对它在所有方面都比较熟悉),所以试图理解如何正确使用线程池对我来说很困难。我使用ApacheMina文档了解应该如何做。我有两个问题: 线程池使用是否正确?ApacheMina的默认线程大小是C
ClientListener cl = new ClientListener(1234);
cl.init();
new Thread(cl).start();
以下是ClientListener的相关代码:
private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1;
private ServerSocket socket;
private ExecutorService threadPool;
private int port;
public ClientListener(int port) {
this.port = port;
threadPool = Executors.newFixedThreadPool(THREADS);
}
public void init() {
try {
socket = new ServerSocket(port);
} catch (IOException ex) {
}
}
public void run() {
while (true) {
try {
ClientSession s = new ClientSession(socket.accept());
threadPool.execute(s);
} catch (IOException ex) {
}
}
}
客户端会话相关代码:
private Socket socket;
private byte[] buffer;
private boolean isHeader;
public ClientSession(Socket socket) {
this.socket = socket;
this.buffer = new byte[4];
this.isHeader = true;
}
public void run() {
InputStream in;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException ex) {
return;
}
while (!socket.isClosed()) {
try {
int read = in.read(buffer);
if (read == -1)
break;
receive(read);
} catch (IOException ex) {
break;
}
}
}
private void receive(int readBytes) {
if (isHeader) {
if (readBytes >= 4) {
buffer = new byte[getPacketLength(buffer)];
isHeader = false;
} else {
System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet.");
}
} else {
if (readBytes >= buffer.length) {
processMessage(new LittleEndianByteArrayReader(decryptData(buffer)), this);
buffer = new byte[4];
isHeader = true;
} else {
System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet (needed " + buffer.length + ", received " + readBytes + ").");
}
}
}
您不需要知道getPacketLength、processMessage、decryptData和LittleEndianByteArrayReader类的代码,但我很确定这些方法/类的目的是显而易见的。阻塞IO场景中的线程数必须根据客户端数和每个客户端连接打开的时间来计算。 每个用户的每个连接都需要一个线程
只有三个线程,用户只需打开三个TCP连接,不向服务器发送任何数据,即可阻塞服务器,直到连接超时 没关系,伙计们。我意识到ApacheMina实际上使用NIO,这就是为什么我感到困惑的原因。使用选择器处理请求实际上只需要一个线程。谢谢你的回答,很抱歉给你带来困惑 突出的是,你只是在吞咽例外。至少把它们记录下来。这些只是代码片段。在我的实际代码中,我使用java.util.Logger和详细的消息来记录它们?我不使用Java的非阻塞I/O类,因为我宁愿使用线程而不是选择器。线程要简单得多。所以我只使用Java的常规同步ServerSocket。将我从异步线程池方法转移到非阻塞选择器方法,这看起来不太令人信服。另外,我希望它能够很好地扩展到多核服务器。这正是我在看到这个关于ApacheMina的网站之前所想的:在标题为“配置I/O工作线程的数量”的部分下,除了I/O处理器线程外,每个工作线程一次只运行一个线程。然而,I/O处理器线程的最大数量是CPU核心数+1,这让我感到困惑。也许它们的工作原理与我所采用的方法不同?这个答案应该是一个评论。