【问题标题】:Java ServerSocket & Sockets no wait for multi-threaded serverJava ServerSocket & Sockets 无需等待多线程服务器
【发布时间】:2014-05-15 20:22:15
【问题描述】:

所以我有一个多线程服务器,并且数据可以正确地来回发送,但是我的写入操作在较慢的连接上停止。我注意到它是按连接时间计算的。第一个连接的客户端总是首先从服务器接收数据。下一个必须等​​到第一个完成接收,依此类推。我正在寻找的是一种无需等待客户端完成接收即可向许多客户端发送数据的服务器。我已经阅读了有关 NIO(非阻塞)的信息,但我真的更喜欢保留我当前的方法,即为每个客户端使用单独的线程。

这是代码。

服务器:

public class Server implements Runnable {

private Thread thread;
private ServerSocket serverSocket;
private ArrayList<ClientThread> clients;

public Server(int port) throws IOException {
    thread = new Thread(this);
    clients = new ArrayList<ClientThread>();
    serverSocket = new ServerSocket(port);
    thread.start();
}

@Override
public void run() {

    while (true) {

        try {
            //Listens to clients connecting.
            ClientThread client = new ClientThread(serverSocket.accept());
            clients.add(client);
            ServerWindow.addText("-- Someone connected!");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

public void broadcast(String data) {
    broadcast(data, null);
}

public void broadcast(String data, ClientThread exclude) {

    int amount = clients.size();

    for (int i = 0; i < amount; i++) {

        if (!clients.get(i).equals(exclude)) { //Don't send it to that client.
            try {
                clients.get(i).broadcast(data);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

}

客户端线程对象:

public class ClientThread implements Runnable {

private Thread thread;
private Socket socket;
private Scanner input;
private PrintWriter output;

public ClientThread(Socket s) throws IOException {
    thread = new Thread(this);
    socket = s;
    socket.setTcpNoDelay(true);
    //socket.setSoTimeout(10); //Send little chunk for 10 milliseconds.
    input = new Scanner(socket.getInputStream());
    output = new PrintWriter(socket.getOutputStream());
    thread.start();
}

public void run() {

    while (true) {          
        if (input.hasNext()) {
            reciever(input.nextLine());
        }
    }
}

private void reciever(String data) {
    ServerWindow.addText(data);
    ServerWindow.server.broadcast(data, this);
}

public void broadcast(String data) throws IOException {
    output.println(data);
    output.flush();
}

}

【问题讨论】:

  • 可以在broadcast中赋值data变量,在run()方法中消费

标签: java multithreading sockets


【解决方案1】:

看来您是从同一个线程调用广播方法。

对于刚接触 Java 中的多线程的用户来说,这是一个常见的陷阱。
广播方法在 Thread 的子类中这一事实并不意味着它将在该线程上执行

实际上它将在调用它的线程上执行。将在您创建的ClientThread 上执行的唯一方法是run() 以及run() 在执行时调用的任何方法。如果您希望所述线程不仅从您的连接中读取数据,而且还写入它,您必须修改 run 方法以侦听外部命令以开始写入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 2015-02-10
    相关资源
    最近更新 更多