JEdi​​torPane甚至冻结了EDT的更新

时间:2014-05-10 05:59:44

标签: java swing

这是一个java聊天应用程序。

Structure of program :
 1. Main thread to connect server(and listen to keyboard input)
 2. I have used EDT to initialize GUI and for action listener
 3. I have started another thread from main thread to grab server messages     

我有一个JEditorPane我从主线程和第二线程更新。我已经使用EDT进行更新,但它仍然被冻结了。我无法弄清楚我在哪里做错了或者我需要重构我的代码

public class Client extends JFrame implements Runnable,KeyListener
{

    private static final long serialVersionUID = 1L;
    static Socket clientSocket=null;
    static BufferedReader is=null, in=null;
    static PrintStream os=null;
    static boolean closed=false;
    static boolean go=false;
    private JPanel contentPane;
    private JComboBox comboT1;
    private JComboBox comboT2;
    private JComboBox comboT3;
    static JEditorPane textArea = new JEditorPane();
    static JTextField write;
    private JButton send;


    public Client()
    {
        setResizable(false);
        setTitle("myStats - Client");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 500, 350);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));



        //textArea = new JTextArea("");
        JScrollPane scroll = new JScrollPane(textArea);

        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        //scroll.setVerticalScrollBarPolicy(ScrollPane.SCROLLBARS_ALWAYS);

        contentPane.add(scroll, BorderLayout.CENTER);

        write = new JTextField();
        write.addKeyListener(this);
        send = new JButton("Send");
        //JLabel writeSomething = new JLabel("Want to send something --");

        Box Vbox = Box.createVerticalBox();     
        Box Hbox = Box.createHorizontalBox();

        Hbox.add(write);
        Hbox.add(Box.createRigidArea(new Dimension(5,0)));
        Hbox.add(send);


        Vbox.add(Box.createRigidArea(new Dimension(0,7)));
        Vbox.add(Hbox);
        contentPane.add(Vbox, BorderLayout.SOUTH);


        send.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //Add my statistics
                go = true;
            }
        });
    }


    public static void main(String args[])
    {
        try
        {
            clientSocket = new Socket("127.0.0.1",8189);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            os = new PrintStream(clientSocket.getOutputStream(),true);
        }
        catch(Exception e)//listening 
        {
            System.out.println("Error : "+e.getMessage());
        }

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Client frame = new Client();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });


        {
            if(clientSocket!=null && os!=null && in!=null)
            {
                try
                {
                    new Thread(new Client()).start();
                    while(!closed)                         //For Keyboard Input -- Message Box
                    {   
                        while(!go);
                        os.println(write.getText());
                        write.setText("");
                        go = false;
                    }
                    os.close();
                    in.close();
                    clientSocket.close();               
                }
                catch(Exception e)
                {
                    System.out.println(e);
                    DoEverything("Error : "+e.getMessage());
                }
            }           
        }   
    }   

    public void run()
    {
        String response;
        try
        {
            while((response=in.readLine())!=null)
            {
                System.out.println(response);
                DoEverything(response);
                if(response.trim().equalsIgnoreCase("Bye"))
                    break;
            }
            closed = true;
        }
        catch(Exception e)
        {
            System.out.println("Error : "+e.getMessage());
            DoEverything("Error : "+e.getMessage());
        }
    }
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {   
            if(write.getText().length()>0)
                send.doClick();
        }
    }
    public static void DoEverything(final String mynew) {
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          textArea.setText(textArea.getText() +""+ mynew+"\n");       
        }
      });
    }

}

这是我的服务器代码

    public class Server
    {
        static Socket clientSocket=null;
        static ServerSocket serverSocket=null;
        static ClientThread threadCollection[] = new ClientThread[20];

        public static void main(String args[])
        {
            int i;
            try


    {
            serverSocket = new ServerSocket(8189);  //Blocking Call -- Wait for Client
        }
        catch(Exception e)
        {
            System.out.println("Error : "+e.getMessage());
        }
        while(true)
        {
            try
            {
                clientSocket = serverSocket.accept(); //get the client details (socket) to interact with them
                for(i=0;i<20;i++)
                {
                    if(threadCollection[i]==null)
                    {
                        threadCollection[i] = new ClientThread(clientSocket, threadCollection);
                        threadCollection[i].start(); //give client server thread(representative)
                        break;
                    }
                }
            }
            catch(Exception e)
            {
                System.out.println("Error : "+e.getMessage());
            }
        }
    }
}

class ClientThread extends Thread
{
    PrintStream os=null; //send the message to client
    BufferedReader is=null; //receive message from client
    Socket clientSocket=null;//client address
    ClientThread threadCollection[];//all the clients server got ~20

    public ClientThread(Socket cs, ClientThread []t)
    {
        this.clientSocket = cs;
        this.threadCollection = t;
    }

    public void run()
    {
        String line = new String();
        int i;
        try
        {
            is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            os = new PrintStream(clientSocket.getOutputStream(),true);


            os.println("<Server> : Hello "+clientSocket.getInetAddress().getHostName());  //server sending message to client

            //name = is.readLine();  //server reading the message from client
            //os.println("Welcome '"+name+"' to chat room!");

            for(i=0;i<20;i++)
                if(threadCollection[i]!=null && threadCollection[i]!=this)
                    threadCollection[i].os.println("A new user '"+clientSocket.getInetAddress().getHostName()+"' joinied to accomplish today's task");

            while(true)
            {
                line = is.readLine();
                System.out.println("<"+clientSocket.getInetAddress().getHostName()+"> : "+line);
                if(line.trim().equalsIgnoreCase("Bye"))
                    break;
                for(i=0;i<20;i++)
                    if(threadCollection[i]!=null)
                        threadCollection[i].os.println("<"+clientSocket.getInetAddress().getHostName()+">: "+line);
            }

            for(i=0;i<20;i++)
                if(threadCollection[i]!=null && threadCollection[i]!=this)
                    threadCollection[i].os.println("User '"+clientSocket.getInetAddress().getHostName()+"' has given up!!!");
            os.println("Bye "+clientSocket.getInetAddress().getHostName());

            for(i=0;i<20;i++)
                if(threadCollection[i]==this)
                    threadCollection[i]=null;

            is.close();
            os.close();
            clientSocket.close();
        }
        catch(Exception e)
        {
            System.out.println("Error : "+e.getMessage());
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您应该声明goclosed volatile:

static volatile boolean closed=false;
static volatile boolean go=false;

这使得每次访问时都可以读取实际变量。如果没有volatile,一个线程可能实际上不会访问原始变量,而是使用另一个值(在时间上早些时候有效)。

循环while (!go);是一个很大的禁忌(带感叹号)。除此之外,如果没有volatile,它可能最终会使用go的过时值,而不会同时检查go变量的实际值。 (简单来说,每个线程都有自己的变量副本,你需要synchronized块来让线程查找真实的东西。)或者你使变量volatile变成了变量&#34; unached& #34;

使用while循环,你想等待。您可以给CPU一些空闲时间来做其他事情而不仅仅占用所有当前的核心:

while (!go) {
   try {
       Thread.sleep(1);
   } catch (InterruptedException e) {
   }
}

之后&#34;而(!go)&#34;你打电话给write.setText("");,但这不在美国东部时间。 (好吧,它可能在EDT中,如果从EDT内部调用main,但通常情况并非如此。)你需要为EDT包装它。

这可能足以消除冻结。 多线程很难。你应该学习wait / notify(仍然很难),特别是看看java.util.concurrent中的类(稍微不那么难)。