Вопрос по java, swing, concurrency, user-interface, sockets – Java Swing GUI зависает

5

Я пишу клиентское / серверное приложение Java с использованием сокетов, и вот проблема:

У меня есть кнопка, чтобы начать прослушивание указанного порта:

кнопка actionPerformed метод

private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    int port = Integer.parseInt(portTextfield.getText(), 10);

    try {
        socket.listen(port);
    } catch (IOException ex) {
    }
}

Вот метод socket.listen

public static void listen() throws IOException {
    ServerSocket ss = new ServerSocket(port);

    while (true)
        new socket(ss.accept());
}

& Quot; гнездо & Quot; класс расширяет & quot; Thread & quot;
Поэтому после того, как ss.accept () возвращает значение, он создает новый экземпляр сокета в отдельном потоке.

После нажатия кнопки графический интерфейс останавливается, потому что внутри метода socket.listen существует бесконечный цикл. Как я могу избежать этого?

и какой твой вопрос, пожалуйста ..., для лучшей помощи, скорее отправь SSCCE mKorbel
Прочитать оConcurrency in Swing. assylias
Для справки приведен рабочий пример.here. trashgod

Ваш Ответ

5   ответов
5

ss.accept() is a blocking call so your UI will freeze until there is an incoming connection Never run while(true) loops in the EDT.

Вместо этого сделайте следующее:

When the button is clicked create a thread that will start listening for incoming connections. Whenever you have an incoming connection, create another thread that will take the incoming client connection and deal with it.
5

пока ваш

new socket(ss.accept());

возвращается немедленно, вам нужно только изменить

while (true)

это помещает EDT (Thread Dispatch Thread) в бесконечный цикл, и ваш GUI перестает отвечать на запросы. Итак, удалите эту строку.

Если вы не можете использовать класс SwingWorker (http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#process(java.util.List) Create a nested class that extents SwingWorker. Just call a swingWoker.execute(); (после того, как вы создали его объект) в вашемlistenButtonActionPerformed(java.awt.event.ActionEvent evt) метод.

Смотрите учебник:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Never create a new thread and run it from from the Swing EDT

3

http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html

1) If you are writing GUI application may be in Swing never call blocking method in Event dispatcher thread or in the event handler. for example if you are reading a file or opening a network connection when a button is clicked don't do that on actionPerformed() method, instead just create another worker thread to do that job and return from actionPerformed(). this will keep your GUI responsive, but again it depends upon design if the operation is something which requires user to wait than consider using invokeAndWait() for synchronous update.

Использование нескольких потоков:http://javarevisited.blogspot.ro/2011/02/how-to-implement-thread-in-java.html

2

1. During getting the initial connection delay can occur, so first create and empty socket,then try to connect to the server.

   `Socket s = new Socket();`

   `s.connect(new InetSocketAddress("ip_addr",port_nos),1000);`

2. And Secondly always keep the Non-UI work out of Your UI thread..

Вот мой пример взаимодействия сервера с клиентом.

Client side code:

public class ClientWala {

    public static void main(String[] args) throws Exception{

        Boolean b = true;
    Socket s = new Socket();
    s.connect(new InetSocketAddress("127.0.0.1", 4444),1000);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}

Server side code:

import java.io.*
import java.net.*;


public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}
3

где вы, я бы разделил код GUI и код сервера, а когда кнопка нажата, я просто запускаю код сервера как новый поток.

Ваш код замораживает графический интерфейс в основном потому, что все события выполняются в потоке диспетчера событий (EDT), который является потоком, который заботится обо всех ваших графических интерфейсах и соответствующих событиях. Если вы заблокируете его, остановите или создадите циклы, это повлияет на его производительность.

Похожие вопросы