3

簡単なチャット プログラムを作成しようとしています。あらゆる種類の例を見つけましたが、ゼロから達成しようとしています。

サーバー クラス (スレッドを拡張) と GUI クラスがあり、[接続] または [切断] ボタンをクリックすると GUI が停止 (スタック) する

サーバーコード:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 *
 * @author Shahar Galukman
 */
public class ChatServer extends Thread{

    ServerSocket ss;
    boolean serverStopped = false;
    private int port = 18524;

    public ChatServer(){
        serverStart();
    }

    private void serverStart(){
        //Create new server socket
        try {
            ss = new ServerSocket(port);
        } catch (Exception e) {
            System.out.println("An error eccurd connection server: " + e.getMessage());
        }
        //wait for clients to connect
        while(!serverStopped){
            try {
                Socket clientSocket = ss.accept();
                /*
                 * Code will halt here until a client socket will be accepted.
                 * Below a new client thread will be created
                 * enabling multi client handling by the server
                */

                //create new ChatClientThread here

            } catch (IOException ex) {
                System.out.println("Error accpeting client socket");
            }
        }
    }
    //Stop the server
    public void stopServer(){
        serverStopped = true;
        ss = null;
    }

}

そして、接続ボタンと切断ボタンを備えたシンプルな SWING GUI を使用しています。Handler という内部クラスを使用して、アクション リスナーをボタンに追加しています。

Handler クラス (GUI クラスの最後にあります:

//inner class
    class Handler implements ActionListener
    {
        //This is triggered whenever the user clicks the login button
            @Override
        public void actionPerformed(ActionEvent ae)
        {
            ChatServer server = new ChatServer();
            //checks if the button clicked
            if(ae.getSource()== connectButton)
            {
                try{
                    server.start();
                    serverStatusField.setText("Connected");
                }catch(Exception e){
                    e.printStackTrace();
                }
            }else if(ae.getSource()== disconnectButton){
                server.stopServer();
                serverStatusField.setText("Disconnected");
            }
        }
    }

また、GUI クラスでは、次のようにアクション リスナーをボタンに追加しています。

public GUI() {
        initComponents();
        //create new handler instance
        handle = new Handler();
        connectButton.addActionListener(handle);
        disconnectButton.addActionListener(handle);
    }

私が理解している限り、接続ボタンをクリックすると、新しいサーバースレッドが開始されます。では、なぜ GUI が動かなくなるのでしょうか。ここでマルチスレッドを使用する必要がありますか?

4

1 に答える 1

4

あなたのserverStart方法では、サーバーが停止するのを待つ一種の無限ループがあります。このボタンが呼び出されると、呼び出し元のスレッドは確実に永久にループし、他の呼び出しをブロックします。

Swing では、GUI はメインスレッドによって処理されます。したがってserverStart、メインスレッドから呼び出すと、ループが壊れるまでGUIがブロックされますが、これは決して起こりません。

serverStartしたがって、はい、マルチスレッドを使用して、別の独立したスレッドを呼び出す必要があります。

通常、次のソリューションを使用する必要があります。

  1. GUI 呼び出し用のスレッド (動的 GUI 処理 ...)
  2. 負荷の高いバックエンド作業用のスレッド (ソケット接続、データ読み込みなど)

編集:

スレッドに関する素晴らしいオラクルのチュートリアルは次のとおりです。

http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

2回目の編集:

コードにも何か問題があります。Thread からオーバーライドされたメソッドではなくserverStart、コンストラクターでメソッドが呼び出されるのはなぜですか? その場合、ChatServer スレッドの構築時にメイン スレッドで無限ループが呼び出されます。Thread の run メソッドで を呼び出す必要があると思います。ChatServerrunserverStart

元:

public class ChatServer extends Thread{
    ....
    public ChatServer(){
    }

    @Override 
    public void run {
        serverStart();
    }
于 2013-04-28T13:34:26.630 に答える