首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java實現監控並自動重啟另一個Java程序

     編輯:Java 相關知識

生產環境常需守護進程:當目標 Java 程序異常退出或需定時重啟時,由監控程序拉起。本文提供基於數據庫信號量 + Runtime.exec() 的雙程序協作方案,含完整代碼與關鍵細節處理。

一、架構設計

  • 程序 A(監控者):輪詢數據庫標誌位,發現「需重啟」信號 → 啟動程序 B
  • 程序 B(被監控):啟動自身監控線程,輪詢標誌位,發現「需關閉」信號 → System.exit(0)
  • 數據庫表 restart:單行單列 status INT,三態:0=運行中、1=請求關閉、2=已關閉待啟動

二、數據庫工具類

public class DBTool {
    private Connection conn;
    private Statement stmt;

    public DBTool() throws Exception {
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        String url = "jdbc:sqlserver://localhost:1433;databaseName=tianjincollect;user=sa;password=123456";
        conn = DriverManager.getConnection(url);
        stmt = conn.createStatement();
    }

    public ResultSet executeQuery(String sql) throws SQLException { return stmt.executeQuery(sql); }
    public int executeUpdate(String sql) throws SQLException { return stmt.executeUpdate(sql); }
    public void close() throws SQLException {
        if (stmt != null) stmt.close();
        if (conn != null) conn.close();
    }
}

三、監控程序 A ReStart

public class ReStart implements Runnable {
    private final DBTool db = new DBTool();
    private final String sqlSel = "SELECT status FROM restart";
    private final String sqlReset = "UPDATE restart SET status = 0";

    @Override public void run() {
        // 初始化狀態
        try { db.executeUpdate(sqlReset); } catch (SQLException e) { e.printStackTrace(); }

        while (true) {
            try {
                ResultSet rs = db.executeQuery(sqlSel);
                if (rs.next()) {
                    int status = rs.getInt("status");
                    System.out.println("檢測狀態: " + status);
                    if (status == 2) { // 已關閉,需啟動
                        System.out.println("啟動目標程序...");
                        db.executeUpdate(sqlReset); // 先重置狀態防止重複啟動
                        // 關鍵:用 cmd /c start 調用批處理,批處理中啟動 java -jar xxx.jar
                        Process p = Runtime.getRuntime().exec("cmd /c start E:\\Bats\\MainThread.bat");
                        p.waitFor();
                    }
                }
            } catch (Exception e) { e.printStackTrace(); }
            sleep(5000);
        }
    }

    private void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException ignored) {} }

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

四、被監控程序 B ExitMain

public class ExitMain implements Runnable {
    private final DBTool db = new DBTool();
    private final String sqlSel = "SELECT status FROM restart";
    private final String sqlSet2 = "UPDATE restart SET status = 2";

    @Override public void run() {
        while (true) {
            try {
                ResultSet rs = db.executeQuery(sqlSel);
                if (rs.next() && rs.getInt("status") == 1) { // 收到關閉指令
                    System.out.println("收到關閉指令,準備退出...");
                    db.executeUpdate(sqlSet2); // 標記已關閉
                    System.exit(0); // 雅退出
                }
            } catch (Exception e) { e.printStackTrace(); }
            sleep(5000);
        }
    }

    private void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException ignored) {} }

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

五、啟動批處理 MainThread.bat

@echo off
java -Xms256m -Xmx512m -jar target-program.jar
rem 程序結束後窗口保持,便於查看日志
pause

六、關鍵細節與改進點

  1. 端口釋放競態:程序 B System.exit() 後,OS 回收端口需時間。程序 A 啟動前 Thread.sleep(5000) 或批處理中 ping -n 5 127.0.0.1 >nul 延遲
  2. 信號量持久化:數據庫表僅作為演示,生產建議用 Redis/ZooKeeper/文件鎖 替代,降低延遲與依賴
  3. 進程檢測更可靠:除信號量外,程序 A 可通過 jps -l 或端口探活確認程序 B 真實存活
  4. 日志與告警:關鍵節點寫入日志文件,異常重啟觸發郵件/鉚釘通知
  5. 優雅關閉:程序 B 捕獲 SIGTERM (Linux) / Ctrl+C (Windows) 執行清理邏輯,而非硬性 System.exit()

七、現代替代方案

  • Systemd / Supervisor / NSSM:作業系統級進程管理,自動重啟、日志輪轉、依賴管理
  • Kubernetes Liveness/Readiness Probe:容器化部署時由 K8s 原生守護
  • Spring Boot Actuator + 外部監控:/actuator/health 暴露健康狀態,Prometheus/Grafana 告警觸發重啟

本方案適合無法使用容器編排、需快速落地的輕量級守護場景;核心思想是「外部監控 + 內部協作 + 狀態持久化」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved