ServerSocket accept的Java主线程未唤醒

ServerSocket accept的Java主线程未唤醒,java,multithreading,sockets,http,Java,Multithreading,Sockets,Http,我正在使用java创建一个简单的web代理应用程序。基本上,main方法创建一个RequestReceiver对象,该对象具有一个ServerSocket,用于侦听web浏览器http请求。从serverSocket.accept返回的套接字创建新的连接对象,并将其放入线程池中 我遇到的问题是,并非所有http GET请求都被serverSocket接收。例如,在我测试的一个网页上,我可以看到代理服务器只接收到10个GET请求中的7个。这会导致网页挂起并需要很长时间才能加载。是什么原因导致ser

我正在使用java创建一个简单的web代理应用程序。基本上,main方法创建一个RequestReceiver对象,该对象具有一个ServerSocket,用于侦听web浏览器http请求。从serverSocket.accept返回的套接字创建新的连接对象,并将其放入线程池中

我遇到的问题是,并非所有http GET请求都被serverSocket接收。例如,在我测试的一个网页上,我可以看到代理服务器只接收到10个GET请求中的7个。这会导致网页挂起并需要很长时间才能加载。是什么原因导致serverSocket.accept函数的线程在建立新连接时不总是获得执行优先级

RequestReceiver.java

public class RequestReceiver {
    public static final int LISTENING_PORT = 4000;
    public static final int CONNECTION_THREAD_POOL_SIZE = 30;

    private ServerSocket serverSocket;
    private ThreadPoolExecutor connectionThreads;

    public RequestReceiver() throws IOException{
        serverSocket = new ServerSocket(LISTENING_PORT);
        connectionThreads = new ThreadPoolExecutor(CONNECTION_THREAD_POOL_SIZE, CONNECTION_THREAD_POOL_SIZE, 
                1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    }

    public void start(){
        try {
            System.out.println("Current Pool Size: " + connectionThreads.getPoolSize() 
                    + " Active threads: " + connectionThreads.getActiveCount() );
            Connection conn = new Connection(serverSocket.accept());
            System.out.println("Created a new connection thread. Request from " + conn.clientSocketToString());
            connectionThreads.execute(conn);
        } catch (IOException e) {
            System.err.println("Exception occured when accepting a new connection.");
            e.printStackTrace();
        }
    }
}

编辑:从catch语句中删除了return语句

当你说10分之7时,你的意思是你测试了10次或几次,得到了这个比率?我这样问是因为默认队列大小是50,所以如果您进行了大量测试,可能会出现队列问题。如果尚未更改队列大小


还有一件事,也是关于队列大小的。您有多个返回并尝试缓存。如果发生任何事情,你将无法达到你的关系密切的程度。因此,当队列已满时,将出现超时,直到当前连接关闭。其他相关问题,资源泄漏

您的服务器套接字似乎接受单个连接,然后退出。有东西在不断地调用start方法吗?@jtahlborn主类有一个whiletrue循环在不断地调用start方法。不要这样编写代码。每个方法应该只有一个catch IOException块。依赖于try块中代码成功与否的代码应位于同一try块中。不要在循环内刷新。它会打印10个创建的新连接线程。来自?@EJP的请求我在编写这段代码时的想法是,通过打印不同的消息,它可以帮助我了解在调试代码的哪个阶段出错。我已经编辑了我的问题以包含清理过的代码。我的意思是,当浏览器发送10个GET请求以加载网站时,只有7个被serverSocket.accept方法拾取并创建了新的连接对象,这是从一个空队列开始的。这是一个公平的观点,我编辑了Connection类以从catch语句中删除return语句。但是,问题仍然存在。我明白了,你能在这里更新吗?因此,我们可以尝试再次帮助您使用新版本;因为你的改变消除了我的答案。很抱歉,我帮不上忙。我希望答案至少是有用的,因为泄漏是真实的。不管我怎么想线程,当连接到达时,你把它放在一个阻塞队列上,队列可能是延迟,因为执行者正在读写它,而连接到达得很快。一个新的连接将不得不等待,直到您在这个阻塞操作之后返回接受。但这不应避免队列上的连接-最多是一个延迟。除非浏览器达到自己的超时。如果你找到了答案,请发到这里,我很好奇。我感谢你的帮助。感谢您指出资源泄漏!这将是一个延迟,但它不应该是一个很长的延迟。如果在加载另一个选项卡时尝试在新选项卡中加载单独的页面,代理也不会接收新的GET请求。这就是为什么我认为有什么东西阻止了主线程获取新的连接。我当然会的!
public class Connection implements Runnable{

public static final int REPLY_CHUNK_SIZE = 32768;
public static final int DEFAULT_WEB_SERVER_PORT = 80;
public static final int SERVER_SOCKET_TIMEOUT = 0; // milliseconds
public static final int CLIENT_SOCKET_TIMEOUT = 0; // milliseconds

private Socket clientSocket, serverSocket;
private InputStream clientIS, serverIS;
private OutputStream clientOS, serverOS;

public Connection(Socket clientSocket){
    this.clientSocket = clientSocket;
    // set client socket timeout
    try{
        clientSocket.setSoTimeout(CLIENT_SOCKET_TIMEOUT);
    }catch(SocketException soe){
        soe.printStackTrace();
    }
}

@Override
public void run() {
    String connection = "";
    try{
        // setup client streams
        clientIS = clientSocket.getInputStream();
        clientOS = clientSocket.getOutputStream();
        // get the request from the browser
        String request = "";
        String hostname = "";
        String[] hostAndPort = new String[2];
        request = browserInputStreamToString(clientIS);
        hostname = getHostName(request);
        hostAndPort = hostname.split(":");
        connection = "Connection to: " + hostname + " from " + clientSocket.getInetAddress().getHostName() 
                + ":" + clientSocket.getPort() + " Request: " + request.split(System.getProperty("line.separator"))[0];
        System.out.println("OPENED>> " + connection);
        // Attempt to create socket to server
        serverSocket = new Socket(hostAndPort[0], (hostAndPort.length > 1 ? new Integer(hostAndPort[1]):DEFAULT_WEB_SERVER_PORT));
        // set timeout
        serverSocket.setSoTimeout(SERVER_SOCKET_TIMEOUT);
        // Set up server streams
        serverIS = serverSocket.getInputStream();
        serverOS = serverSocket.getOutputStream();
        // send client request to server
        serverOS.write(request.getBytes());
        serverOS.flush();
        // send server response to client in chunks
        byte[] reply = new byte[REPLY_CHUNK_SIZE];
        int replyLength = serverIS.read(reply);
        while( replyLength != -1 ){
            clientOS.write(reply, 0, replyLength);
            clientOS.flush();
            replyLength = serverIS.read(reply);
        }
        // close sockets
        clientSocket.close();
        serverSocket.close();
    }catch(Exception e){
        e.printStackTrace();
    } finally{
        try {
            if(clientSocket != null){
                clientSocket.close();
            }
            if(serverSocket != null){
                serverSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    System.out.println("CLOSED>> " + connection);
}