Вопрос:

Java Swing GUI зависает

java swing sockets user-interface concurrency

10393 просмотра

5 ответа

423 Репутация автора

Я пишу клиентское / серверное приложение 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());
}

класс «socket» расширяет «Thread».
Таким образом, после того, как ss.accept () возвращает значение, он создает новый экземпляр сокета в отдельном потоке.

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

Автор: Nick Sanders Источник Размещён: 25.06.2012 08:01

Ответы (5)


3 плюса

47733 Репутация автора

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

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

Автор: npinti Размещён: 25.06.2012 08:03

3 плюса

3435 Репутация автора

Проверьте это: http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html

1) Если вы пишете приложение GUI, возможно, в Swing никогда не вызывайте метод блокировки в потоке диспетчера событий или в обработчике событий. например, если вы читаете файл или открываете сетевое соединение при нажатии кнопки, не делайте этого в методе actionPerformed (), вместо этого просто создайте другой рабочий поток для выполнения этой работы и вернитесь из actionPerformed (). это будет поддерживать отзывчивость вашего графического интерфейса, но опять-таки это зависит от дизайна, если операция - это то, что требует от пользователя ожидания, а не использования invokeAndWait () для синхронного обновления.

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

Автор: CosminO Размещён: 25.06.2012 08:08

5 плюса

16271 Репутация автора

Решение

У вас есть две ловушки в вашем дизайне:

  1. ss.accept() это блокирующий вызов, поэтому ваш пользовательский интерфейс будет зависать, пока не будет входящее соединение
  2. Никогда не запускайте while(true)циклы в EDT.

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

  • При нажатии кнопки создайте поток, который начнет прослушивать входящие соединения.
  • Если у вас есть входящее соединение, создайте другой поток, который будет принимать входящее клиентское соединение и обрабатывать его.
Автор: GETah Размещён: 25.06.2012 08:36

5 плюса

11539 Репутация автора

пока ваш

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 ), создайте вложенный класс, который Extents SwingWorker. Просто вызовите swingWoker.execute (); (после того, как вы создали его объект) в вашем методе listenButtonActionPerformed (java.awt.event.ActionEvent evt) .

См. Учебное пособие: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html.

Никогда не создавайте новую тему и не запускайте ее из Swing EDT

Автор: vedant Размещён: 25.06.2012 08:41

2 плюса

30339 Репутация автора

Попробуйте это...

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..

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

Код на стороне клиента:

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

    }




    }
}

Код серверной части:

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

    }

}
Автор: Kumar Vivek Mitra Размещён: 25.06.2012 03:08
Вопросы из категории :
32x32