Java 与同步和线程间通信混淆

Java 与同步和线程间通信混淆,java,multithreading,parallel-processing,synchronization,thread-safety,Java,Multithreading,Parallel Processing,Synchronization,Thread Safety,我被问到了这个问题,从几天以来我一直在尝试,但我无法得到正确的输出。任何帮助都将不胜感激 使用发送-等待-接收协议在两个用户之间开发一个简单的聊天应用程序: 一旦一个用户发送了一条消息,他就会等待,直到收到来自另一个用户的消息。用户是User1和User2 在应用程序的初始阶段,User1处于发送模式,User2处于接收模式。这两个用户交替地发送和接收消息。 -使用两种方法创建聊天类:sendMessage和RecVMMessage -创建两个线程来表示两个用户,User1和User2。 -使用

我被问到了这个问题,从几天以来我一直在尝试,但我无法得到正确的输出。任何帮助都将不胜感激

使用发送-等待-接收协议在两个用户之间开发一个简单的聊天应用程序:

一旦一个用户发送了一条消息,他就会等待,直到收到来自另一个用户的消息。用户是User1和User2

在应用程序的初始阶段,User1处于发送模式,User2处于接收模式。这两个用户交替地发送和接收消息。 -使用两种方法创建聊天类:sendMessage和RecVMMessage -创建两个线程来表示两个用户,User1和User2。 -使用线程间通信来交换消息。 -无需维护任何聊天记录

输出:

用户1用户2:嗨

User2User1:嗨

User2User1:你好

用户1用户2:您好

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之间交替进行,一次一个。这个问题现在清楚一点了吗?是的,它起作用了,非常感谢