简体   繁体   中英

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. It has been crunching data since 2 days, suddenly today logs which i print after processing each record from the excel stopped.

After some examination found that mongodb has become unresponsive due to which i assume that all the threads are waiting for response. 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. This part of the code is written inside a finally block. 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. 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. I mean making sure that the code inside the finally block gets executed. 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.

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.

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. The validate method is called from the run() method overridden from the thread class.

added a part of the jstack output::

"Attach Listener" #13759 daemon prio=9 os_prio=0 tid=0x00007fddd0001000 nid=0x11ba waiting on condition [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 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 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)

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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