1

我正在尝试为多线程服务器程序保持连接打开。当我点击一个按钮时,我希望它向所有连接的客户端发送一条测试消息。

public void run() {
    try {
        Scanner in = new Scanner(socket.getInputStream());
        PrintWriter out = new PrintWriter(socket.getOutputStream());
        readUpdate(out, in);
        while(true){sendUpdate(out);}
    } catch (Exception e) {
        e.printStackTrace();
    }
}

使用大量 CPU。

这是我的 sendUpdate 方法。

private void sendUpdate(final PrintWriter out) {
    new Thread(new Runnable() {

        public void run() {
            if(Server.send) {
                try {
                    if (Server.command != "idle") {
                        System.out.println("Sending");
                        out.println("!msg@" + Server.command);
                        out.flush();
                        Server.send = false;
                        Thread.sleep(100);
                    }
                } catch (Exception ex) {
                }
            }
        }
    }).start();
}

如果有人可以帮助我保持连接打开并准备发送数据,我将不胜感激。

4

1 回答 1

1

如果您的服务器可以启动消息,您的客户端也可以,您可能需要一个单独的线程读取和写入。一个线程对于请求-响应式通信是有意义的,您可以在其中阻塞下一个客户端请求,进行一些服务器端处理,响应客户端,然后再次阻塞。

但是,如果您需要阻止两个单独的条件(从客户端接收消息并单击服务器上的按钮),那么您应该有两个单独的线程。否则,您会发现自己需要反复唤醒线程以检查其中任何一个条件是否为真。

所以创建两个线程,一个是你的Scanner(做readUpdate逻辑的),另一个是你的PrintWriter。这就是您的输出处理程序的样子:

public class WriteHandler implements Runnable {
    private final PrintWriter out;
    private final BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();

    //initialize the above in a constructor;

    public void run() {
       while(true) {
          String nextMessageToWrite = messageQueue.poll();
          out.println(nextMessageToWrite);
       }
    }

    public void send(String message) {
        messageQueue.add(message);
    }
}

这使用了一个阻塞队列,这是一种比检查睡眠循环更好的并发机制。然后当点击按钮时,你可以有这样的东西:

public void actionPerformed() {
    for ( WriteHandler handler : handlers ) {
        handler.send("PING!");
    }
}
于 2012-07-08T17:45:26.163 回答