简体   繁体   English

如何优雅地停止在 eclipse 中运行的 java 主程序

[英]How to gracefully stop a java main program running inside eclipse

I am running a script in eclipse ( java main method program ) which creates threads where each thread processes an excel sheet and then saving the processed data into database.我在 eclipse(java main 方法程序)中运行一个脚本,它创建线程,其中每个线程处理一个 Excel 工作表,然后将处理后的数据保存到数据库中。 It has been crunching data since 2 days, suddenly today logs which i print after processing each record from the excel stopped.从 2 天起它一直在处理数据,今天突然我在处理完 excel 中的每条记录后打印的日志停止了。

After some examination found that mongodb has become unresponsive due to which i assume that all the threads are waiting for response.经过一些检查发现 mongodb 变得无响应,因此我认为所有线程都在等待响应。 I have restarted my database thinking the program will throw an error but no error was thrown.我重新启动了我的数据库,认为程序会抛出错误,但没有抛出错误。

The way that my code is written is that after processing a complete sheet it writes a status message into the excel sheet records.我的代码的编写方式是,在处理完一张完整的工作表后,它会在 Excel 工作表记录中写入一条状态消息。 This part of the code is written inside a finally block.这部分代码写在 finally 块中。 I have been waiting for the program to terminate by itself but it is still running.我一直在等待程序自行终止,但它仍在运行。 I have checked it to be running because i take input from user for a new excel sheet to read.我已经检查它正在运行,因为我从用户那里获取输入以读取新的 Excel 表。 It is taking input from the user and printing logs.它从用户那里获取输入并打印日志。 Therefore i assume the program hasn't become unresponsive.因此,我认为该程序并没有变得无响应。

Is there a way to safely shutdown my program so that all the status logs get printed into the excel sheet.有没有办法安全地关闭我的程序,以便所有状态日志都打印到 Excel 表中。 I mean making sure that the code inside the finally block gets executed.我的意思是确保 finally 块中的代码得到执行。 There are no shutdown hooks written in the script.脚本中没有编写关闭挂钩。 The status logs are very important as i have been running this program since the past 2 days.状态日志非常重要,因为我自过去 2 天以来一直在运行该程序。

According to this link killing a program using kill -15 would be safer as it might give the program to do some clean up operations but i'm not sure.根据此链接,使用 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();
                }
            }
        }
    }

There are no sleep or wait methods being called inside "validateAndProcessData" method.在“validateAndProcessData”方法中没有调用睡眠或等待方法。 The validate method is called from the run() method overridden from the thread class. validate 方法是从线程类重写的 run() 方法调用的。

added a part of the jstack output::添加了一部分 jstack 输出::

"Attach Listener" #13759 daemon prio=9 os_prio=0 tid=0x00007fddd0001000 nid=0x11ba waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE “附加监听器”#13759 守护进程 prio=9 os_prio=0 tid=0x00007fddd0001000 nid=0x11ba 等待条件 [0x0000000000000000] java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers: - None锁定的可拥有同步器: - 无

"ThreadID:13" #12918 prio=5 os_prio=0 tid=0x00007fde1c89f000 nid=0x155 runnable [0x00007fdde8bec000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:170) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) at java.io.BufferedInputStream.read1(BufferedInputStream.java:286) at java.io.BufferedInputStream.read(BufferedInputStream.java:345) - locked <0x0000000760ccd5b8> (a java.io.BufferedInputStream) at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704) at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1536) - locked <0x0000000760cc9168> (a sun.net.www.protocol.http.HttpURLConnection) at sun.net.www.protocol.http.HttpURLConnection.getInp "ThreadID:13" #12918 prio=5 os_prio=0 tid=0x00007fde1c89f000 nid=0x155 runnable [0x00007fdde8bec000] java.lang.Thread.State: 在 java.net.SocketInputStreamInput0(java.net.SocketInputStream Method.socket.) RUNNABLE .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) at java.io.BufferedInputStream.read1(BufferedInputStream.java:286) at java.io.BufferedInputStream.read(BufferedInputStream.java:345) - 在太阳处锁定 <0x0000000760ccd5b8>(一个 java.io.BufferedInputStream)。 net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704) at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0( HttpURLConnection.java:1536) - 在 sun.net.www.protocol.http.HttpURLConnection.getInp 锁定 <0x0000000760cc9168>(一个 sun.net.www.protocol.http.HttpURLConnection) utStream(HttpURLConnection.java:1441) - locked <0x0000000760cc9168> (a sun.net.www.protocol.http.HttpURLConnection) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:321) at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:227) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246) at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:667) at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:664) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:664) at org.glassfish.jersey.client.JerseyInvoc utStream(HttpURLConnection.java:1441) - 在 org.glassfish.jersey.client 的 java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) 锁定 <0x0000000760cc9168>(一个 sun.net.www.protocol.http.HttpURLConnection) .HttpUrlConnector._apply(HttpUrlConnector.java:321) at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:227) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246) at 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) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish .jersey.process.internal.RequestScope.runInScope(RequestScope.java:424) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:664) at org.glassfish.jersey.client.JerseyInvoc ation$Builder.method(JerseyInvocation.java:399) at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:303) at transaction.script.excelSheet.validators.ExcelSheetsValidator.getlocation(ExcelSheetsValidator.java:428) at transaction.script.excelSheet.validators.ExcelSheetsValidator.validateAndProcessData(ExcelSheetsValidator.java:231) at transaction.script.excelSheet.validators.ExcelSheetsValidator.validate(ExcelSheetsValidator.java:137) at transaction.script.excelSheet.validators.ExcelSheetsValidator.run(ExcelSheetsValidator.java:122) at java.lang.Thread.run(Thread.java:745) ation$Builder.method(JerseyInvocation.java:399) 在 org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:303) 在 transaction.script.excelSheet.validators.ExcelSheetsValidator.getlocation(ExcelSheetsValidator.java: 428) at transaction.script.excelSheet.validators.ExcelSheetsValidator.validateAndProcessData(ExcelSheetsValidator.java:231) at transaction.script.excelSheet.validators.ExcelSheetsValidator.validate(ExcelSheetsValidator.java:137) at transaction.script.excelSheet.validators.ExcelSheetsValidator .run(ExcelSheetsValidator.java:122) 在 java.lang.Thread.run(Thread.java:745)

Locked ownable synchronizers: - None锁定的可拥有同步器: - 无

You might have tried this already, but I guess if you have some kind of exception handling for database connection timeout, it might solve your problem.您可能已经尝试过这个,但我想如果您对数据库连接超时有某种异常处理,它可能会解决您的问题。

I am basing this on the line where you have given After some examination found that mongodb has become unresponsive due to which i assume that all the threads are waiting for response.我基于你给出的那一行经过一些检查发现 mongodb 变得没有响应,因此我假设所有线程都在等待响应。

You can input a char in the console when you want to shutdown当你想关机时,你可以在控制台输入一个字符

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM