对于学校的项目,我们在Java 5.0中创建一个多线程服务器。该项目以服务器的并发方面为中心。
我们有一些致力于处理请求的线程。为此,他们调用ServerSocket.accept()来接受新连接。我们的选择是启动它们并让它们处理传入的连接,假设两个线程不能同时接受()相同的连接。
但现在主要的问题是我们在API中找不到保证我们这种行为的任何东西(或者我们看起来不对),除了“它的工作”证明之外什么也没有。
是否有人来寻找有关java方法的这类信息?
答案 0 :(得分:25)
简短回答:如果文档没有指定某些东西是线程安全的,那么你必须假设它不是。您需要自己在线程之间进行协调,以确保没有两个线程同时使用服务器套接字。
这一点尤为重要,因为其他一些代码可以使用ServerSocket.setSocketFactory
注册自己的套接字实现。即使默认套接字实现是线程安全的,也不一定是自定义实现。文档中没有任何内容表明这一点。
答案很长:默认Windows实施
您可以下载并检查java SE 1.6 source code。
我从\j2se\src\share\classes\java\net\ServerSocket.java
开始,然后从那里开始PlainSocketImpl.java
。 PlainSocketImpl.Accept
方法标记为native
。
Windows的本机C ++代码位于\j2se\src\windows\native\java\net\PlainSocketImpl.c
。它使用winsock accept函数。来自MSDN article on WinSock(强调我的):
在Windows NT和Windows 2000下, Windows套接字支持16位 应用程序基于WINSOCK.DLL。 对于32位应用程序,支持 在WSOCK32.DLL中。提供的API 除了32位之外是相同的 版本的参数扩大到32 位。 在Win32下,线程安全性是 提供。强>
所以至少在Windows上,Socket.Accept
是线程安全的,因为它不会让两个线程接受相同的连接。 ServerSocket
实现中也有基础结构(例如,Close()方法使用锁),表明它是线程安全的。
答案 1 :(得分:9)
这并没有完全回答你的问题,但在多个线程上运行accept()听起来好像服务器的设计有问题。
通常不需要从多个线程运行accept()。
您的代码应如下所示:
while (serverIsUpAndRunning())
{
// Wait for an incoming connection.
Socket s = serverSocket.accept();
// Spawn a thread to handle the socket,
// so that we don't block new connections.
SocketHandlerThread t = new SocketHandlerThread(s);
t.start();
}