使用线程技术开发基于java的聊天应用程序

使用线程技术开发基于java的聊天应用程序,java,multithreading,Java,Multithreading,我试图通过线程发送消息。dataAvailable是一个变量,用于指示消息是否在textfield上可用。若available dataAvailable设置为true,若为true,则在run()方法中执行以下代码。但问题在于run()中,它从未看到dataAvailable为true,并且未发送任何内容。需要帮助 我是客户 import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.even

我试图通过线程发送消息。dataAvailable是一个变量,用于指示消息是否在textfield上可用。若available dataAvailable设置为true,若为true,则在run()方法中执行以下代码。但问题在于run()中,它从未看到dataAvailable为true,并且未发送任何内容。需要帮助

我是客户

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class PeerOne extends JFrame implements Runnable
{
    private static final long serialVersionUID = 1L;

    JTextField outgoing;
    JTextArea incoming;
    JButton send;
    Thread t,t1;
    ObjectOutputStream output;  //for writing objects to a stream
    ObjectInputStream input;    //for reading objects from a stream
    Socket s;
    volatile boolean dataAvailable=false;
    String message = null;
    public PeerOne()
    {
        outgoing = new JTextField();
        outgoing.setEnabled(true);
        outgoing.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(!(e.getActionCommand().isEmpty()))
                {
                    dataAvailable = true;
                    System.out.print("hi");
                }
            }
        });

        this.add(outgoing,BorderLayout.SOUTH);

        incoming = new JTextArea();
        incoming.setEditable(true);
        this.add(new JScrollPane(incoming),BorderLayout.CENTER);
        this.add(incoming);

        setSize(300,150);
        setVisible(true);

        try
        {
            s = new Socket("localhost",5500);
            incoming.append("Connection Successfull..."+"\n");

            output = new ObjectOutputStream(s.getOutputStream());
            output.flush();
            input = new ObjectInputStream(s.getInputStream());

        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }

        t = new Thread(this,"PeerOne");
        System.out.print("New Thread");
        //t1 = new Thread(this,"Two");
        t.start();
    }

    public static void main(String[] args) 
    {
        new PeerOne();
    }

    public void run()
    {   
        while(true)
        {
            if(dataAvailable==true)
            {
                try 
                {
                    System.out.print(0);
                    output.writeObject(outgoing.getText());
                    output.flush();
                    dataAvailable = false;
                }
                catch (IOException e1) 
                {
                    e1.printStackTrace();
                }
            }
            try 
            {
                try 
                {
                    message = (String)input.readObject();

                    incoming.append(message);
                }
                catch (ClassNotFoundException e) 
                {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }       
        }

    }
}
这是服务器

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class PeerTwo extends JFrame implements Runnable
{
    private static final long serialVersionUID = 1L;
    JTextField outgoing;
    JTextArea incoming;
    JButton send;
    Thread t;
    Socket s;   
    ObjectOutputStream output;  //for writing objects to a stream
    ObjectInputStream input;    //for reading objects from a stream
    volatile boolean dataAvailable=false;
    String message = null;

    public PeerTwo()
    {
        outgoing = new JTextField();
        outgoing.setEnabled(true);
        outgoing.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(!(e.getActionCommand().isEmpty()))
                {
                    dataAvailable = true;
                }
            }
        });

        this.add(outgoing,BorderLayout.SOUTH);

        incoming = new JTextArea();
        incoming.setEditable(true);
        this.add(new JScrollPane(incoming),BorderLayout.CENTER);
        this.add(incoming);

        setSize(300,150);
        setVisible(true);
        try
        {
            ServerSocket ss = new ServerSocket(5500,100);
            s = ss.accept();

            output = new ObjectOutputStream(s.getOutputStream());
            output.flush();
            input = new ObjectInputStream(s.getInputStream());
        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }

        t = new Thread(this,"PeerTwo");
        System.out.print("New Thread");
        t.start();



    }

    public static void main(String[] args)
    {
        new PeerTwo();
    }

    public void run() 
    {
            while(true)
            {
                if(dataAvailable==true)
                {
                    try 
                    {
                        System.out.print("bbb");
                        output.writeObject(outgoing.getText());
                        output.flush();
                        dataAvailable = false;
                    }
                    catch (IOException e1) 
                    {
                        e1.printStackTrace();
                    }
                }
                try {
                        try 
                        {
                            message = (String)input.readObject();
                            System.out.print(0);
                            incoming.append(message);
                        }
                        catch (ClassNotFoundException e) 
                        {
                            e.printStackTrace();
                        }
                } catch (IOException e) {
                    e.printStackTrace();
                }       
            }
        }
}

此代码有几个错误/问题:

  • 无止境的循环。您的代码浪费处理器时间。我建议将其用于写过程或至少用于睡眠
  • 读取被阻止。代码没有任何来自输入流的检查
  • 在室外使用回转组件
  • 当您关闭应用程序窗口时,应用程序仍然工作。(使用此.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);)
  • 所以我想建议热修复。它将使您的代码正常工作。 PeerOne(客户):

    PeerTwo(服务器):


    因此,正如您所知,我修复了1-3个问题,并使用readUTF/writeUTF代替readObject/writeObject来简化代码。下一步是将读/写拆分为两个单线程。您可以自己做。

    您有两个dataAvailable变量,它们位于不同的类中,因此不共享;设置一个并不设置另一个。dataAvailable用于限制写入输出流,但用于读取消息的代码不受任何条件语句的限制。当dataAvailable在PeerOne中为true时,运行()应该能够读取dataAvailable为true并发送消息,但事实并非如此,如果我将条件写为dataAvailable==false,它将发送msgDidn。您昨天不是在另一个帐户下尝试问同样的问题吗?您有两个dataAvailable变量。我们不打算申请生产,但欢迎提出建议。很好地一个接一个地指出了问题。
    public void run() {
            while (true) {
                if (dataAvailable == true) {
                    try {
                        System.out.print(0);
                        output.writeUTF(outgoing.getText());
                        output.flush();
                        dataAvailable = false;
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                try {
                    if (input.available() > 0) {
                        message = input.readUTF();
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                incoming.append(message);
                                incoming.append("\n");
                            }
                        });
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    public void run() {
        while (true) {
            if (dataAvailable == true) {
                try {
                    System.out.print("bbb");
                    output.writeUTF(outgoing.getText());
                    output.flush();
                    dataAvailable = false;
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            try {
                if (input.available() > 0) {
                    message = input.readUTF();
                    System.out.print(0);
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            incoming.append(message);
                            incoming.append("\n");
                        }
                    });
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                TimeUnit.MILLISECONDS.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }