即使在其他线程中启动,帧也会冻结

时间:2013-08-30 17:16:29

标签: java multithreading swing freeze

我希望在我的程序与其他玩家连接时显示一个Frame。但即使Frame在他自己的Thread中运行,它仍然会在Serversocket尝试连接时冻结。如何防止它冻结?

public static boolean connectH(String check, String data, int k){
    ServerSocket serverSocket = null;
    Socket clientSocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    message = "waiting for someone to connect to your " + check + "-game";
    th = new Thread(){
        @Override
        public void run() {
            c = new Canceler(message);
        }
    };
    th.start();
    try {
        serverSocket = new ServerSocket(Integer.parseInt(data));
    } catch (IOException e) {
        JOptionPane.showMessageDialog(null, "Could not listen on port: " + data);
        Main.m.finishgame(-1);
    }


    try {
        clientSocket = serverSocket.accept();
    } catch (IOException e) {
        System.err.println("Accept failed.");
        System.exit(1);
    }

    try {
        out = new PrintWriter(clientSocket.getOutputStream(), true);
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        if (in.readLine().equals(check)){
            out.println(k);
            c.remove();
            return true;
        }else{
            out.println(String.valueOf(-1));
            c.remove();
            return false;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    c.remove();
    return false;
}

1 个答案:

答案 0 :(得分:1)

也许这个例子Applet会让你入门。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class Example extends JApplet
{
    private JButton _jButtonStartGameServer;
    private boolean _isStarted = false;
    private GameServer _gameServer = null;
    private JTextArea _jTextArea;
    private Thread _gameServerThread = null;
    private boolean _initialized = false;

    public Example()
    {
        System.out.println("ctor...");
    }

    private void initComponents()
    {
        if (_initialized)
        {
            return;
        }

        _jButtonStartGameServer = new JButton("Start Game Server");
        _jButtonStartGameServer.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                if (!_isStarted)
                {
                    startupGameServer();
                }
                else
                {
                    shutdownGameServer();
                }
            }
        });
        setLayout(new BorderLayout(0, 0));

        _jTextArea = new JTextArea();
        add(_jTextArea);
        add(_jButtonStartGameServer, BorderLayout.NORTH);

        _initialized = true;
    }

    public void init()
    {
        System.out.println("init... " + Thread.currentThread());
        try
        {
            SwingUtilities.invokeAndWait(new Runnable()
            {
                public void run()
                {
                    initComponents();
                }
            });
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }

    public void start()
    {
        System.out.println("start... " + Thread.currentThread());
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                setSize(640/2, 480/2);
            }
        });
    }

    public void stop()
    {
        System.out.println("stop... " + Thread.currentThread());
        shutdownGameServer();
    }

    public void destroy()
    {
        System.out.println("destroy " + Thread.currentThread());
        shutdownGameServer();
    }

    void displayException(Throwable t)
    {
        log("Got exception: " + t);
    }


    void processMessageFromOtherPlayer(String msg)
    {
        log("Received message from other player: " + msg);
    }

    void gameServerThreadExiting()
    {
        shutdownGameServer();
    }

    public void startupGameServer()
    {
        _gameServer = new GameServer();
        _gameServerThread = new Thread(_gameServer);
        _gameServerThread.start();
        _isStarted = true;
        _jButtonStartGameServer.setText("Stop Game Server");
    }

    public void shutdownGameServer()
    {
        GameServer gs = _gameServer;
        if (gs != null)
        {
            gs.cancel();
        }
        Thread t = _gameServerThread;
        try
        {
            if (t != null)
            {
                t.join();
            }
        }
        catch (InterruptedException ie)
        {
            Thread.currentThread().interrupt();
        }
        _gameServer = null;
        _jButtonStartGameServer.setText("Start Game Server");
        _isStarted = false;
    }

    void log(final String msg)
    {
        System.out.println("Log (" + Thread.currentThread() + "): " + msg);
        Runnable r = new Runnable()
        {
            public void run()
            {
                StringBuilder sb = new StringBuilder(_jTextArea.getText());
                sb.append(msg);
                sb.append("\n");
                _jTextArea.setText(sb.toString());
            }
        };
        if (SwingUtilities.isEventDispatchThread())
        {
            r.run();
        }
        else
        {
            SwingUtilities.invokeLater(r);
        }
    }

    class GameServer implements Runnable
    {
        volatile ServerSocket _ss = null;
        volatile Socket _s = null;
        volatile InputStream _sis = null;
        volatile boolean _cancel = false;

        public void run()
        {
            try
            {
                _ss = new ServerSocket(9999);
                log("Waiting for other player, listening on port: " + _ss.getLocalPort());
                _s = _ss.accept();
                log("Connection accepted from: " + _s.getRemoteSocketAddress());
                _sis = _s.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(_sis, "UTF-8"));
                while (true)
                {
                    if (_cancel)
                    {
                        break;
                    }
                    final String msg = br.readLine();
                    if (msg == null)
                    {
                        // connection closed / lost
                        break;
                    }
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            processMessageFromOtherPlayer(msg);
                        }
                    });
                }
            }
            catch (final Throwable t)
            {
                // don't show the user the exception if the user is canceling
                if (!_cancel)
                {
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            displayException(t);
                        }
                    });
                }
                else
                {
                    // even if the user is canceling, we might be interested in the exception, though
                    t.printStackTrace();
                }
            }
            log("Game server thread exiting...");
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    gameServerThreadExiting();
                }

            });
        }

        public void cancel()
        {
            _cancel = true;

            ServerSocket ss = _ss;
            if (ss != null)
            {
                try
                {
                    ss.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }

            Socket s = _s;
            if (s != null)
            {
                try
                {
                    s.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }

            InputStream sis = _sis;
            if (sis != null)
            {
                try
                {
                    sis.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}