1

ハードリブート(電源ボタンを押したままにする)をしなければならなかったのはとても悪いことで、デバッグする時間すら与えられないので、ここで答えが得られないと基本的に台無しになります。私はそれがサーバー側であることを知っています(クライアントを実行していないときに発生しますが、実行した場合にも発生します)。

サーバーコードは次のとおりです。

package cypri.games.cybatarserver;

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

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class CybatarServer extends JFrame implements Runnable{
    String verNum = "0.0.0";
    JScrollPane jsp;
    JTextArea mainText;
    boolean stopServer = false;
    boolean waitForPlayers = true;
    Vector<Player> playersConnected;
    byte playerID = -1;

    public CybatarServer(){
        playersConnected = new Vector<Player>();

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setBounds(100, 100, 400, 100);

        this.setTitle("Cybatar Server " + verNum);

        mainText = new JTextArea(50, 10);
        mainText.setText("Welcome to CybatarServer "+ verNum + "!\n");
        mainText.setEditable(false);

        jsp = new JScrollPane(mainText);
        this.add(jsp);

        this.setVisible(true);
    }

    public static void main(String[] args){
        CybatarServer cyserv = new CybatarServer();
        cyserv.run();
    }

    @Override
    public void run() {

        try { 
            final ServerSocket serverSocket = new ServerSocket(44444);


            while(!stopServer){
                if(waitForPlayers){
                    new Thread(new Runnable() {
                        public void run() {

                            Socket clientSocket = null;
                                try {
                                    clientSocket = serverSocket.accept();
                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                                playerID++;
                                new PlayerThread(playerID, playersConnected, mainText, playerID, clientSocket).start();
                                mainText.append("Player " + playerID + " connected!");

                        }
                    }).start();
                }

                else{
                    for(int i = 0; i < playersConnected.size(); i++){
                        playersConnected.get(i).update();
                    }
                }

                Thread.yield();
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
}

PC が完全にフリーズする原因となるものはありますか? もしそうなら、どうすれば修正できますか?

4

4 に答える 4

11

疑う

while(!stopServer){
   if(waitForPlayers){
       new Thread(new Runnable() {
         ....

膨大な数のスレッドを生成および呼び出しています。これは、CPU (これらのスレッドを実行する) とメモリ (各スレッドが独自のスタック領域を割り当てる) の点でマシンに大きな影響を与えます。

代わりに、着信接続を受け入れてから、スレッド割り当て/開始したいのではないかと思います。これでも DOS 攻撃を受ける可能性はあることに注意してください (無制限の数のプレイヤーが参加した場合を想像してください) が、それは実際的な問題ではない可能性があります。

于 2012-07-10T16:29:00.787 に答える
3

補足: UI スレッドで UI を実行します

この部分:

while(!stopServer){
    if(waitForPlayers){
         new Thread(...).start();
     }
}

stopServer または waitForPlayers フラグがかなり迅速に変更されない限り、膨大な数のスレッドが作成されます。ハングしても不思議ではありません...

于 2012-07-10T16:30:22.867 に答える
2

に設定waitForPlayersしていないようですfalse。そのため、ループするたびwhile(!stopServer)に新しいスレッドが生成され、コンピューターがフリーズします。

于 2012-07-10T16:29:36.487 に答える
1

明らかにそれを実行しようとしたことはありませんが、この構成は潜在的なフォーク爆弾として私を襲います:

              new Thread(new Runnable() {
                    public void run() {
                            ...
                            new PlayerThread(playerID, playersConnected, mainText, playerID, clientSocket).start();
                            ...
              }
于 2012-07-10T16:29:57.657 に答える