0

UDP メッセージをリッスンするシンプルなアプリがあります。アプリは無期限に実行する必要があります。作成した MySQLConnect オブジェクトをインスタンス化することで、単一の jdbc データベース接続をインスタンス化します。次のようになります。

 public MySQLConnect() {
    this.instantiateConnection();
}

//Open the database connection.  Done iniitally in 
//the main class and only called again if the connection 
//is closed due to an error in processing a message
public Connection instantiateConnection() {

    try {

        Class.forName("com.mysql.jdbc.Driver");

        connection = DriverManager
                .getConnection("jdbc:mysql://localhost:3306/mydb?"
                        + "user=user&password=pwd");
    } catch (Exception e) {
        e.printStackTrace();
    }

    return connection;
}

MySQLConnect クラス コンストラクターは、アプリが起動されると、UDPReceiver クラスから呼び出されます。その後、エラー処理が発生し、データベース接続が閉じられた場合にのみ再度呼び出されます。このクラスは次のようになります。

 public class UDPReceiver {

private static int port = 2140;
private static int byteSize = 1024;
private static int timeOut = 5000;
@SuppressWarnings("unused")
private static int count;
static MySQLConnect dbConnect;


   public static void main(String[] args) {

    recvUDPMessage();
}

public static String recvUDPMessage() {
    DataTransferService dts = new DataTransferServiceImp();
    dbConnect = new MySQLConnect();

    try {

        DatagramSocket dsocket = null;
        if (dsocket == null) {
            dsocket = new DatagramSocket(port);
            dsocket.setBroadcast(true);
            dsocket.setReuseAddress(false);
        }
        byte[] inbuf = new byte[byteSize];
        byte[] rcvMsg;
        InetAddress fromIP;

        DatagramPacket receivepacket = new DatagramPacket(inbuf,
                inbuf.length);
        dsocket.setSoTimeout(timeOut);

        //Infinitely loop and listen for UDP messages

        count = 0;
        boolean loopRecv = true;
        while (loopRecv) {
            try {
                count++;
                dsocket.receive(receivepacket);
                // temp = receivepacket.getAddress().toString();
                fromIP = receivepacket.getAddress();
                String fromIPString = fromIP.toString();
                rcvMsg = receivepacket.getData();
                String rcvString = new String(rcvMsg, 0, rcvMsg.length);
                String rcvMessage = "Message Received from:  "
                        + fromIPString + " Message:  " + rcvString + "\n";
                System.out.println(rcvMessage);



                ArrayList<String> al = getMessageElements(rcvString);



                //Send array of message elements to service layer
                dts.saveUDPMessage(dbConnect, al, Utils.getTimeStamp());

                loopRecv = true;
            } catch (IOException e) {
                System.out.println("Listening . . .");



                loopRecv = true;
            }
        }
    } catch (SocketException e) {
        System.err.println("Sockets Exception: " + e.getMessage());
    } catch (Exception e) {
        System.err.println(" Exception: " + e.getMessage());

    } finally {
        System.out.println(". . . Close DB");
        dts.closeDBConnection(dbConnect);


                    // I added the creation MySQLConnect object after I was getting an error that the database was closed when trying to insert.
        dbConnect = new MySQLConnect();
    }
    return "end of routine";
}

//Extract comma delimited message elements into an array
private static ArrayList<String> getMessageElements(String rcvString) {
    StringTokenizer st = new StringTokenizer(rcvString, ",");

    ArrayList<String> al = new ArrayList<String>();

    while (st.hasMoreElements()) {
        String messageElement = (String) st.nextElement();
        al.add(messageElement);

    }



    return al;
}

}

これは約 8 時間実行され、次のエラーが表示されます。

スレッドのメイン java.lang.stackoverflowerror での例外

例外: メインスレッドの uncaughtexceptionhandler から java.lang.outofmemoryerror がスローされました

以前は、データベースが閉じられた後に MySQLConnect オブジェクトを再インスタンス化しませんでした。問題は、データベース接続が閉じられたというエラーを受け取ったことですが、私のプログラムはまだ jdbc 挿入を実行しようとしていました。jdbc挿入は、最初にインスタンス化された接続があるかどうかを確認し、インスタンス化されていない場合はインスタンス化します。MySQLConnect クラスのこのコードは次のようになります。

 PreparedStatement prep = null;

    if (connection == null) {
        connection = this.instantiateConnection();
    }

    try {

        prep = connection
                .prepareStatement("insert into MyTable (UDPMessage)"
                        + "values (?);");

        prep.setString(1, udpMessage);




        prep.addBatch();

        prep.executeBatch();

UDP メッセージを無期限に処理し、エラーが発生した場合でもデータベースに書き込むように、このプロセスを正しく設計するにはどうすればよいでしょうか?

また、データの処理中に例外が発生したときに MySQLConnect クラスを再インスタンス化するときにメモリ不足エラーが発生することを解決するにはどうすればよいですか?

例外の後にこのクラスをインスタンス化することが正しくない場合、データベースへの接続を再インスタンス化してデータの処理を続行するにはどうすればよいですか?

ご協力いただきありがとうございます!

4

3 に答える 3

1

ループを終了するには

while (loopRecv) {
...
}

そうでない場所をマークする必要がありますloopRecv=false;

于 2012-08-10T18:18:18.227 に答える
1

コードのどこにもブール値loopRecvを設定していないfalseため、無限ループにつながります (条件は常に に解決されtrueます)。無限/再帰ループは、スタックに移入し続けますが、スタック フレームを削除せず、StackOVerflowError.

于 2012-08-10T17:57:27.117 に答える
0

同期性について心配していない場合は、ループの内容を別のスレッド内に配置してみませんか。そのスレッドを一度実行すると、破棄されます。次に、無限ループで、別のスレッドを作成して実行します。これらのスレッドは自分自身を破棄し、スタックから削除されます。

于 2012-08-10T18:08:36.103 に答える