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

Working on a java based chatting application using threading

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*

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..."+"
"
);

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

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*

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


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

  • 无止境的循环。您的代码浪费处理器时间。我建议在写过程或至少睡眠时使用保护块。
  • 读取被阻止。代码没有任何来自输入流的检查。
  • 在EDT外使用回转部件
  • 关闭应用程序窗口时,应用程序仍能工作。(使用此.setDefaultCloseOperation(jframe.exit-on-close);)
  • 所以我想推荐热修复程序。它将使您的代码工作。Peerone(客户端):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    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("
    "
    );
                            }
                        });
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    PeerTwo(服务器):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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("
    "
    );
                        }
                    });
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                TimeUnit.MILLISECONDS.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    因此,我修复了1-3个问题,并使用readutf/writeutf代替readobject/writeobject来简化代码。下一步是将读/写拆分为2个单线程。你可以自己做。