我正在尝试使用RMI与服务器和多个客户端进行非常简单的控制台聊天,只是为了好玩。
对于客户端,会显示一个菜单,并且需要输入。同时,有一个线程在循环中运行,听取请愿。
如果其他客户希望与此聊天,他将收到通知,他必须决定是否与该其他客户聊天。这就是问题所在。菜单正在等待输入,现在通知正在等待另一个。所以我们有两个,但我只是想对第二个做出回应,我想忽略第一个和我输入的任何输入到通知选择。
如何“销毁”第一个等待输入,以便客户端可以只响应该通知?
答案 0 :(得分:-1)
为了“销毁”正在等待输入的 Scanner,break;
while
循环。下面是一个例子:
import java.util.Scanner;
public class test {
public static void main(String args[]) {
while(true){
System.out.println("Type ':cwoc' to chat with another client!");
Scanner check1 = new Scanner(System.in);
String userInput1 = check1.nextLine();
////////////
//Put your code of whatever you want here
////////////
if (userInput1.equals(":cwoc")){//chat with other client (cwoc)
break; // 'destroys'(breaks) client 1
} else {
continue;
}
}
System.out.println("Type 'hello client 2' to say hi!");
Scanner check2 = new Scanner(System.in);
String userInput2 = check2.nextLine();
////////////
//Second Client Code (It could also lead to a function)
////////////
if (userInput2.equals("hello client 2")){
System.out.println("Hi client 1!");
}
}
}
输出如下:
正如您在输出中看到的那样,每次客户端 1 键入内容时,客户端 1 的 AI 都会做出响应。客户端 1 发送与客户端 2 聊天的请求 (:cwoc) 后,它break;
循环响应客户端 1,并激活客户端 2 的 AI。
答案 1 :(得分:-1)
如果我理解正确,你可以用 2 个线程解决这个问题;一个将等待来自服务器的传入请求(我们称之为 networkThread
),另一个将等待来自用户的输入(keyboardThread
)。如果您的 keyboardThread
线程刚刚将 networkThread
打印到控制台,您希望用户对 There is an incoming chat from Fred, accept?
的输入有不同的解释。您现在的问题是(可能)处理键盘输入的代码对传入请求一无所知。让我们通过添加另一个确实知道正在发生的一切的对象来改变这一点:
public interface KeyboardListener {
void handleInput(String input); // handle keyboard input
}
public interface NetworkListener {
void handleChatRequest(Chat request); // handle incoming chat request
}
public class Controller implements KeyboardListener, NetworkListener {
private Chat chat = null; // currently active chat
private boolean chatting = false; // if true, chat is active
void handleInput(String input) {
synchronized (this) {
if (chat != null) {
if (chatting) {
chat.send(input);
} else if (":accept".equals(input)) {
chatting = true;
chat.send("Chat accepted!");
} else if (":reject".equals(input)) {
chat.send("Chat rejected!");
chat.close();
chat = null;
}
} // ... many more states & commands can be handled here
}
}
void handleChatRequest(Chat request) {
synchronized (this) {
System.out.println("Incoming request from " + request.name()
+ " - write :accept to accept it, or :reject to reject it");
if (chatting) {
request.send("User is already chatting with someone else");
} else {
chat = request;
request.send("Awaiting user to accept request");
}
}
}
}
因此您只需要启动接收 相同 KeyboardThread
对象的 NetworkThread
和 Controller
(但 KeyboardThread
认为它是一个 KeyboardListener
,而另一个认为它只是一个 NetworkListener
)。每当每个线程有话要说时,它都会调用控制器的相应 handleXxx
方法——它知道要做什么。 synchronized
块用于防止两个线程同时尝试调用处理程序,否则会导致 race condition 和潜在的意外行为。