Java多线程套接字 - 如何不按顺序发送响应

时间:2017-04-15 19:32:07

标签: java multithreading sockets

对于我所看到的问题的冗长描述感到抱歉。

我有下面记录的代码,我一直试图让它使用线程不按顺序发送消息。我继续在客户端上获得以下控制台输出。

  

回显客户端消息:您好:0 14210577 14210579

     

回显客户端消息:您好:1 14211379 14211379

     

回显客户端消息:您好:2 14212181 14212181

     

回显客户端消息:您好:3 14212981 14212982

     

回显客户留言:您好:4 14213782 14213782

     

回显客户端消息:您好:5 14214582 14214583

     

回显客户留言:您好:6 14215383 14215383

     

回显客户端消息:您好:7 14216184 14216184

     

回显客户端消息:您好:8 14216984 14216984

     

回显客户留言:您好:9 14217785 14217785

我希望实现的客户端上的控制台输出类似于以下内容(消息2之后的所有消息都在消息2之前发送)

  

回显客户端消息:您好:0 14210577 14210579

     

回显客户端消息:您好:1 14211379 14211379

     

回显客户端消息:您好:3 14212981 14212982

     

回显客户留言:您好:4 14213782 14213782

     

回显客户端消息:您好:5 14214582 14214583

     

回显客户留言:您好:6 14215383 14215383

     

回显客户端消息:您好:7 14216184 14216184

     

回显客户端消息:您好:8 14216984 14216984

     

回显客户留言:您好:9 14217785 14217785

     

回显客户留言:您好:2 14212181 14217885

客户端上的控制台输出具有以下内容:我可以看到,在消息2完成其等待时间之前,不会发送服务器对消息3的响应。我希望服务器在消息2完成等待之前将其响应发送到消息3。

  

传入客户端消息:您好:2 15430652

     

在ServerThread中调用Send Message:15430653

     

从ServerThread中的发送消息返回:15430653

     sendMessage.doWork()中的

:15430653

     

sendMessage.doWork()完成等待:15430753

     

传入客户端消息:您好:3 15430753

如何让线程继续处理其他消息而不必等待消息2等待完成?

提前感谢任何输入。

服务器类:

// Built off the following tutorials
// https://www.youtube.com/watch?v=2cQJJwoSNLk
// https://www.youtube.com/watch?v=nCIw0h1C8Qo

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

public class Server{

    public static void main(String[] args) {
        try {
            new Server().runServer();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void runServer() throws IOException{
        final int PORT = 4444;
        ServerSocket serverSocket = new ServerSocket(PORT);
        System.out.println(new StringBuilder().append("Server up and ready for connections...").toString());
        while(true){
            Socket socket = serverSocket.accept();
            new Thread(new ServerThread(socket)).start();
        }
    }

    public class ServerThread implements Runnable{

        private Socket socket;
        private String message;

        ServerThread(Socket socket){
            this.socket = socket;
        }

        public void run(){

            try {
                this.message = null;
                PrintWriter printWriter = new PrintWriter(socket.getOutputStream(),true);
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader (socket.getInputStream()));
                while((message = bufferedReader.readLine()) != null){
                    System.out.println(new StringBuilder().append("incoming client message: ").append(message).toString());
                    long sendTime = System.nanoTime();
                    if(message.trim().startsWith("Hello: 2")){
                        sendTime = System.nanoTime() + 100000000;
                    }

                    System.out.println(new StringBuilder().append("calling Send Message in ServerThread: ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString());

                    new Thread( 
                            new SendMessage(printWriter, 
                                            sendTime, 
                                            new StringBuilder().append("echoing client message: ").append(message).append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()
                                            )
                            ).start();

                    System.out.println(new StringBuilder().append("returned from Send Message in ServerThread: ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString());
                }
            } catch (IOException e) {
            }

        }

    }

}

客户类:

// Built off the following tutorials

// https://www.youtube.com/watch?v=2cQJJwoSNLk

// https://www.youtube.com/watch?v=nCIw0h1C8Qo



import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

import java.net.UnknownHostException;

import java.util.concurrent.TimeUnit;


public class Client {

public static final int PORT = 4444;

public static void main(String[] args) throws UnknownHostException, IOException {

    Socket socket = new Socket("localhost",PORT);
    PrintWriter printWriter = new PrintWriter(socket.getOutputStream(),true);
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    for(int x = 0; x<10;x++){
        if(x==5){
            printWriter.println(new StringBuilder().append("Hello: ").append(x).append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString());
        }else{
            printWriter.println(new StringBuilder().append("Hello: ").append(x).append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString());
        }
        System.out.println(new StringBuilder().append(bufferedReader.readLine()));
    }
    //socket.close();
}


}

SendMessage类:

import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

public class SendMessage implements Runnable{

private PrintWriter printWriter;
private Long SendTimeInNanos;
private String message;

public SendMessage(PrintWriter printWriter, Long SendTimeInNanos, String message){
    this.printWriter = printWriter;
    this.SendTimeInNanos = SendTimeInNanos;
    this.message = message;
}

@Override
public void run() {
    doWork();
}

private void doWork(){
    System.out.println(new StringBuilder().append("in sendMessage.doWork(): ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString());
    //sleep until the appropriate time
    while(this.SendTimeInNanos > System.nanoTime()){
        try {
            //sleep until appropriate time
            Thread.sleep(TimeUnit.NANOSECONDS.toMillis(this.SendTimeInNanos-System.nanoTime()));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    System.out.println(new StringBuilder().append("sendMessage.doWork() done waiting: ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString());

    //send at appropriate time
    this.printWriter.println(new StringBuilder().append(this.message).toString());
}

}

1 个答案:

答案 0 :(得分:0)

总体而言,您的代码看起来不错。问题可能在于您创建和启动线程的方式:

  while(true){
        Socket socket = serverSocket.accept();
        new Thread(new ServerThread(socket)).start();
    }

看起来每个新线程在创建新线程之前都会很快完成执行。要实现异步线程执行,请尝试创建多个ServerThread实例并立即启动所有实例:

  while(true){
        Socket socket = serverSocket.accept();
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 4; i++)
        {
            threads.add(new Thread(new ServerThread(socket)));
        }
        threads.forEach(Thread::start);
 }