使用线程处理基于Java的聊天应用程序

时间:2013-12-17 16:48:00

标签: java multithreading

我试图通过线程发送消息。 dataAvailable是一个变量,它告诉消息是否在textfield上可用。如果可用dataAvailable设置为true,则在run()方法中如果在执行代码后为true。但问题是在run()中它从未看到dataAvailable为true且没有发送任何内容。需要帮助。

/*

This is client

*/ 
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();
            }       
        }

    }
}

/*

This is server

*/
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();
                }       
            }
        }
}

1 个答案:

答案 0 :(得分:2)

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

  1. 无尽的循环。您的代码浪费处理器时间。我建议使用guarded block进行写程序或至少睡觉。
  2. 读取被阻止。代码没有从输入流中进行任何检查。
  3. EDT
  4. 之外使用swing组件
  5. 关闭应用程序窗口时,应用程序仍然有效。 (使用this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);)
  6. 所以我想建议修补程序。它将使您的代码工作。 PeerOne(客户端):

    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();
                }
            }
        }
    

    PeerTwo(服务器):

    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();
            }
        }
    }
    

    因此,我可以修复1-3个问题并使用readUTF / writeUTF而不是readObject / writeObject来简化代码。下一步是拆分读/写2个单线程。你可以自己做。