【问题标题】:How to gracefully stop a java main program running inside eclipse如何优雅地停止在 Eclipse 中运行的 Java 主程序
【发布时间】:2017-02-12 14:02:50
【问题描述】:

我在 eclipse(java main 方法程序)中运行一个脚本,它创建线程,每个线程处理一个 excel 表,然后将处理后的数据保存到数据库中。自 2 天以来一直在处理数据,今天突然间我在处理来自 excel 的每条记录后打印的日志停止了。

经过一些检查,发现 mongodb 已变得无响应,因此我假设所有线程都在等待响应。我重新启动了我的数据库,以为程序会抛出错误,但没有抛出错误。

我的代码编写方式是,在处理完一张完整的工作表后,它会在 Excel 工作表记录中写入一条状态消息。这部分代码写在 finally 块中。我一直在等待程序自行终止,但它仍在运行。我已经检查它是否正在运行,因为我从用户那里获取输入以读取新的 Excel 表。它正在接受用户的输入并打印日志。因此,我认为该程序没有变得无响应。

有没有办法安全地关闭我的程序,以便将所有状态日志打印到 Excel 表中。我的意思是确保 finally 块中的代码被执行。脚本中没有编写关闭挂钩。状态日志非常重要,因为我过去 2 天一直在运行这个程序。

根据这个link 使用 kill -15 杀死程序会更安全,因为它可能会让程序进行一些清理操作,但我不确定。

public static void validate(String sheetNameWithLocation, String threadName) {
        String fileName = sheetNameWithLocation.substring(sheetNameWithLocation.lastIndexOf("/") + 1);
        Workbook workbook = null;
        try (FileInputStream inputStream = new FileInputStream(sheetNameWithLocation);) {
            workbook = new XSSFWorkbook(inputStream);
            Sheet dataSheet = workbook.getSheet(AppConstants.DATA_SHEET);
            if (dataSheet != null) {
                String countryName = fileName.split("_")[0];
                long startTime = System.currentTimeMillis();
                for (int i = 1, count = 1; i <= dataSheet.getLastRowNum() && !shouldICleanUpAndStop; i++, count++) {
                    try {
                        validateAndProcessData(countryName, dataSheet, i, threadName);
                    } catch (Exception e) {
                        e.printStackTrace();
                        LOGGER.error(threadName + "::Exception occurred for record number:" + i + " Message is :: " + e.getMessage());
                    }
                    LOGGER.info(threadName + "::status is :: Processed " + count + " records in " + (System.currentTimeMillis() - startTime) + " ms");
                }
                LOGGER.info(threadName + "::Total time taken to process sheet is::" + (System.currentTimeMillis() - startTime) + " ms");
            } else {
                LOGGER.error(threadName + "::DATA sheet is not present. Program exiting....");
            }
        } catch (FileNotFoundException e) {
            LOGGER.error("Unable to locate file");
            e.printStackTrace();
        } catch (IOException e) {
            LOGGER.error("Unable to load or write to file.");
            e.printStackTrace();
        } finally {
            if (workbook != null) {
                try (FileOutputStream outputStream = new FileOutputStream(sheetNameWithLocation);) {
                    workbook.write(outputStream);
                } catch (FileNotFoundException e) {
                    LOGGER.error("Unable to locate file");
                    e.printStackTrace();
                } catch (IOException e) {
                    LOGGER.error("Unable to load or write to file.");
                    e.printStackTrace();
                }
            }
        }
    }

在“validateAndProcessData”方法中没有调用睡眠或等待方法。 从线程类覆盖的 run() 方法调用 validate 方法。

添加了 jstack 输出的一部分::

“附加监听器”#13759 守护进程 prio=9 os_prio=0 tid=0x00007fddd0001000 nid=0x11ba 等待条件 [0x0000000000000000] java.lang.Thread.State: 可运行

锁定的可拥有同步器: - 无

"ThreadID:13" #12918 prio=5 os_prio=0 tid=0x00007fde1c89f000 nid=0x155 可运行 [0x00007fdde8bec000] java.lang.Thread.State:可运行 在 java.net.SocketInputStream.socketRead0(本机方法) 在 java.net.SocketInputStream.socketRead(SocketInputStream.java:116) 在 java.net.SocketInputStream.read(SocketInputStream.java:170) 在 java.net.SocketInputStream.read(SocketInputStream.java:141) 在 java.io.BufferedInputStream.fill(BufferedInputStream.java:246) 在 java.io.BufferedInputStream.read1(BufferedInputStream.java:286) 在 java.io.BufferedInputStream.read(BufferedInputStream.java:345) - 锁定 (一个 java.io.BufferedInputStream) 在 sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704) 在 sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1536) - 锁定(sun.net.www.protocol.http.HttpURLConnection) 在 sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) - 锁定(sun.net.www.protocol.http.HttpURLConnection) 在 java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) 在 org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:321) 在 org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:227) 在 org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246) 在 org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:667) 在 org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:664) 在 org.glassfish.jersey.internal.Errors.process(Errors.java:315) 在 org.glassfish.jersey.internal.Errors.process(Errors.java:297) 在 org.glassfish.jersey.internal.Errors.process(Errors.java:228) 在 org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424) 在 org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:664) 在 org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:399) 在 org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:303) 在 transaction.script.excelSheet.validators.ExcelSheetsValidator.getlocation(ExcelSheetsValidator.java:428) 在 transaction.script.excelSheet.validators.ExcelSheetsValidator.validateAndProcessData(ExcelSheetsValidator.java:231) 在 transaction.script.excelSheet.validators.ExcelSheetsValidator.validate(ExcelSheetsValidator.java:137) 在 transaction.script.excelSheet.validators.ExcelSheetsValidator.run(ExcelSheetsValidator.java:122) 在 java.lang.Thread.run(Thread.java:745)

锁定的可拥有同步器: - 无

【问题讨论】:

  • 请出示您的代码
  • @NicolasFilotto 我添加了部分代码
  • 使用jstack 获取堆栈跟踪。这样你就可以找出程序到底卡在哪里了。
  • @talex 我已经添加了 jstack 你能帮我理解吗
  • ExcelSheetsValidator.getlocation(ExcelSheetsValidator.java:428) 中的内容

标签: java eclipse multithreading


【解决方案1】:

你可能已经尝试过了,但我想如果你对数据库连接超时有某种异常处理,它可能会解决你的问题。

我是根据你给出的那一行经过一些检查发现 mongodb 已经变得无响应,因此我认为所有线程都在等待响应。

【讨论】:

    【解决方案2】:

    你想关机时可以在控制台输入一个字符

    public static void main(String[] args) throws Exception {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("close");
            }
        });
        SpringApplication.run(Application.class, args);
        System.in.read();
        System.exit(0);
    }
    

    【讨论】:

    • 感谢您的回答。但我的问题是针对已经在 Eclipse 中运行的程序。无法添加新代码并处理此问题。
    猜你喜欢
    • 1970-01-01
    • 2011-03-12
    • 2023-03-16
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    相关资源
    最近更新 更多