Java 与同步和线程间通信混淆
我被问到了这个问题,从几天以来我一直在尝试,但我无法得到正确的输出。任何帮助都将不胜感激 使用发送-等待-接收协议在两个用户之间开发一个简单的聊天应用程序: 一旦一个用户发送了一条消息,他就会等待,直到收到来自另一个用户的消息。用户是User1和User2 在应用程序的初始阶段,User1处于发送模式,User2处于接收模式。这两个用户交替地发送和接收消息。 -使用两种方法创建聊天类:sendMessage和RecVMMessage -创建两个线程来表示两个用户,User1和User2。 -使用线程间通信来交换消息。 -无需维护任何聊天记录 输出: 用户1用户2:嗨 User2User1:嗨 User2User1:你好 用户1用户2:您好Java 与同步和线程间通信混淆,java,multithreading,parallel-processing,synchronization,thread-safety,Java,Multithreading,Parallel Processing,Synchronization,Thread Safety,我被问到了这个问题,从几天以来我一直在尝试,但我无法得到正确的输出。任何帮助都将不胜感激 使用发送-等待-接收协议在两个用户之间开发一个简单的聊天应用程序: 一旦一个用户发送了一条消息,他就会等待,直到收到来自另一个用户的消息。用户是User1和User2 在应用程序的初始阶段,User1处于发送模式,User2处于接收模式。这两个用户交替地发送和接收消息。 -使用两种方法创建聊天类:sendMessage和RecVMMessage -创建两个线程来表示两个用户,User1和User2。 -使用
class Chat{
Scanner sc=new Scanner(System.in);
String message;
ArrayList<String> user1 = new ArrayList<String>();
ArrayList<String> user2 = new ArrayList<String>();
boolean sendMode = true;
String name = "";
String otherName = "";
synchronized void recvMessage(){
name = Thread.currentThread().getName();
while(sendMode) {
try{
wait();
}catch(InterruptedException e){
System.out.println("InterruptedException caught");
}
}
System.out.println(name);
if (name.contentEquals("User1")) {
otherName="User2";
}
else {
otherName="User1";
}
System.out.println(name+"("+otherName+"):" + message);
sendMode=true;
System.out.println("rcv");
notify();
}
synchronized void sendMessage(){
name = Thread.currentThread().getName();
while(!sendMode) {
try{
wait();
}catch(InterruptedException e){
System.out.println("InterruptedException caught");
}
}
System.out.println(name);
if (name.contentEquals("User1")) {
otherName="User2";
}
else {
otherName="User1";
}
System.out.print(name+"("+otherName+"):");
message=sc.next();
if(name.contains("User1")) {
user1.add(message);
}
else {
user2.add(message);
}
System.out.println("send");
sendMode=false;
notify();
}
}
class Person1 implements Runnable{
Chat ex;
public Person1(Chat ex) {
this.ex = ex;
Thread u2=new Thread(this, "User1");
u2.start();
}
public void run() {
while(true) {
ex.sendMessage();
}
}
}
class Person2 implements Runnable{
Chat ex;
public Person2(Chat ex) {
this.ex=ex;
Thread u1=new Thread(this, "User2");
u1.start();
}
public void run() {
while(true) {
ex.recvMessage();
}
}
}
class Main{
public static void main(String args[])
{
Chat ex =new Chat();
new Person1(ex);
new Person2(ex);
}
}
我得到的结果是:
用户1用户2:嗨
User2User1:嗨
User2User1:你好
用户1用户2:您好
用户2用户1:怎么了
用户1用户2:这是什么
User2User1:User1User2:up
User2User1:
基本上,线程没有按顺序完成它们的工作。输出的前4行是正确的。但是在那之后,总是user2发送消息,user1接收消息
请帮助我。您的代码有两个问题,第一个问题是您正在使用:
message=sc.next();
相反,您应该使用:
message=sc.nextLine();
使用next将只返回分隔符前面的内容
默认为空白。nextLine自动移动扫描仪
返回当前行后关闭
从这个
这就是为什么对于第一个不带空格的输入,它可以正常工作,但只要发送带空格的字符串:
what's up
你遇到了问题
第二部分是,在当前设计中,只有一个线程发送,另一个线程接收。为了让双方都能相互交流,而不是独白,我建议做如下事情:
class Chat{
Scanner sc=new Scanner(System.in);
String message;
final Object rec = new Object();
final Object send = new Object();
boolean msg_send = false;
boolean msg_recv = false;
void recvMessage(){
synchronized (send){
while(!msg_send) {
try{
send.wait();
}catch(InterruptedException e){
System.out.println("InterruptedException caught");
}
}
msg_send = false;
}
synchronized (rec) {
String name = Thread.currentThread().getName();
System.out.println(name);
String otherName = name.contentEquals("User1") ? "User2" : "User1";
System.out.println(name + "(" + otherName + "):" + message);
System.out.println("rcv");
msg_recv = true;
rec.notify();
}
}
void sendMessage(){
synchronized (send) {
String name = Thread.currentThread().getName();
System.out.println(name);
String otherName = name.contentEquals("User1") ? "User2" : "User1";
System.out.print(name + "(" + otherName + "):");
message = sc.nextLine();
System.out.println("send");
msg_send = true;
send.notify();
}
synchronized (rec) {
while (!msg_recv) {
try {
rec.wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
msg_recv = false;
}
}
}
class Person1 implements Runnable{
Chat ex;
public Person1(Chat ex) {
this.ex = ex;
Thread u2=new Thread(this, "User1");
u2.start();
}
public void run() {
while(true) {
ex.sendMessage();
ex.recvMessage();
}
}
}
class Person2 implements Runnable{
Chat ex;
public Person2(Chat ex) {
this.ex=ex;
Thread u1=new Thread(this, "User2");
u1.start();
}
public void run() {
while(true) {
ex.recvMessage();
ex.sendMessage();
}
}
}
class Main{
public static void main(String args[])
{
Chat ex =new Chat();
new Person1(ex);
new Person2(ex);
}
}
使用两个表示何时接收和发送消息的对象进行等待和通知:
final Object rec = new Object();
final Object send = new Object();
然后,您需要关于何时应在一个或另一个对象上同步的原因。谢谢。这也是一个问题,但主要问题是线程没有交替地发送和接收消息。正如您在我的输出中所看到的,首先user1将消息发送给user2,然后user2接收消息。接下来,情况正好相反。但是第三次以后,它总是由user2向user1发送消息,而user1只是接收该消息。用户1在第一次之后无法再发送消息。否。我不擅长线程间通信,但我知道它与wait和notify方法有关。代码的逻辑似乎是正确的。好吧,user1必须向user2发送一条消息,user2应该会收到它。有发送和接收的方法。然后user2应该向user1发送一条消息,user1应该接收它。发送和接收应该在user1和user2之间交替进行,一次一个。这个问题现在清楚一点了吗?是的,它起作用了,非常感谢