简体   繁体   中英

Unexpected multithreaded result and timing

I wrote a simple server. When do I run this server and then immediately open 3 tabs in browser with uri localhost:7777 I expect thread by request, in my case it is 3
simultaneously threads (every thread starts at same time and die at about the same time).

But I see in console output that first thread started at 0(local minutes):11(local seconds) then second thread started at 0:11 but stopped(why? it's not independent thread?) at reading loop block and resumed execution only after awaking(0:16) of first thread and third thread runs only when the second thread dies(0:21).

I expecting following timing:

Connected with Thread-1 0:11 
Connected with Thread-2 0:11 
Connected with Thread-3 0:11 
Disconnect with Thread-1 0:16
Disconnect with Thread-2 0:16
Disconnect with Thread-3 0:16

What I missed? Why second thread waits awaking of first thread and third thread starts only after death of second thread?

public class Starter {

    public static void main(String args[]){

    int port = 7777;
        try {

            final ServerSocket socket = new ServerSocket(port);
            new Thread(new ThreadPool(socket)).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




public class ThreadPool implements Runnable{

protected ServerSocket socket;

public ThreadPool(ServerSocket socket){
    this.socket = socket;
}

@Override
public void run() {

    final ExecutorService executors = Executors.newCachedThreadPool();

    while(true){
        try {
            final Socket acceptedSocket = this.socket.accept();
            //executors.execute(new ThreadWork(acceptedSocket));
            new Thread(new ThreadWork(acceptedSocket)).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
}



public class ThreadWork implements Runnable {

protected final Socket clientSocket;

public ThreadWork(Socket clientSocket){
    this.clientSocket = clientSocket;
}

@Override
public void run() {
    try {
        System.out.println("Connected with " + java.lang.Thread.currentThread().getName() + " " + ((System.currentTimeMillis() / 1000*60) % 60) + ":" + ((System.currentTimeMillis() / 1000) % 60));
        System.out.println("   " + clientSocket.toString());

        InputStream sin = clientSocket.getInputStream();
        OutputStream sout = clientSocket.getOutputStream();

        BufferedReader in = new BufferedReader(new InputStreamReader(sin));
        OutputStreamWriter out = new OutputStreamWriter(sout);

        String line =
                "HTTP/1.1 200 OK\n"  +
                        "Date: Thu, 19 Feb 2009 12:27:04 GMT\n"       +
                        "Server: Apache/2.2.3\n"                         +
                        "Last-Modified: Wed, 18 Jun 2003 16:05:58 GMT\n"       +
                        "Content-Type: text/html\n"             +
                        "Content-Length: 115\n"      +
                        "Accept-Ranges: bytes\n"      +
                        "Connection: close\n"  +
                        "\r\n" +
                        "<html><head><title>Hello</title></head><body>It Works!</body></html>\n";

        String requestLine;

        System.out.println("      Before reading " + java.lang.Thread.currentThread().getName() + " " + ((System.currentTimeMillis() / 1000*60) % 60) + ":" + ((System.currentTimeMillis() / 1000) % 60));
        while((requestLine = in.readLine()) != null) {
            if(requestLine.isEmpty()){
                break;
            }
        }
        System.out.println("         Asleep " + java.lang.Thread.currentThread().getName());
        java.lang.Thread.sleep(5000);
        System.out.println("         Awake " + java.lang.Thread.currentThread().getName());
        out.write(line);
        out.flush();
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    finally {
        try {
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println("Disconnect with " + java.lang.Thread.currentThread().getName() + " " + ((System.currentTimeMillis() / 1000*60) % 60) + ":" + ((System.currentTimeMillis() / 1000) % 60));
    }
}
}

Program output

Connected with Thread-1 0:11
   Socket[addr=/0:0:0:0:0:0:0:1,port=45416,localport=7777]
      Before reading Thread-1 0:11
         Asleep Thread-1
Connected with Thread-2 0:11
   Socket[addr=/0:0:0:0:0:0:0:1,port=45419,localport=7777]
      Before reading Thread-2 0:11
         Awake Thread-1
Disconnect with Thread-1 0:16
         Asleep Thread-2
         Awake Thread-2
Disconnect with Thread-2 0:21
Connected with Thread-3 0:21
   Socket[addr=/0:0:0:0:0:0:0:1,port=45424,localport=7777]
      Before reading Thread-3 0:21
         Asleep Thread-3
         Awake Thread-3
Disconnect with Thread-3 0:26

As far as I can see, there's nothing wrong with your code. The same thing happens for me, however, so I tried running it myself while monitoring the network traffic with tcpdump , and it seems it's simply the browser playing tricks, not your code.

I'm using Chromium, and it simply doesn't send the second request until the first one is complete, nor does it even connect the third time until then. I'm guessing it's trying to be kind to the server by not overloading it, or something.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM