简体   繁体   English

意外的多线程结果和计时

[英]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 我什么时候运行此服务器,然后立即在浏览器中使用uri localhost:7777打开3个标签,我希望通过请求获得线程,在我的情况下是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). 但是我在控制台输出中看到,第一个线程在0(本地分钟):11(本地秒)开始,然后第二个线程在0:11开始,但是在读取循环块时停止了(为什么?它不是独立线程?),仅在之后仅当第二个线程死亡(0:21)时,第一线程和第三线程的唤醒(0:16)才会运行。

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. 但是,对我来说也发生了同样的事情,因此我尝试在自己使用tcpdump监视网络流量时运行它,这似乎只是浏览器在玩弄技巧,而不是您的代码。

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. 我正在使用Chromium,它只是在第一个请求完成之前才发送第二个请求,甚至直到那时都没有连接第三次。 I'm guessing it's trying to be kind to the server by not overloading it, or something. 我猜想它试图通过不重载服务器或其他方式来对服务器友好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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