当前位置: 首页 > 面试题库 >

线程不会在run()结束时自然退出

慕高阳
2023-03-14
问题内容

我的问题是这样的: 即使读取完成(数百万行)的文件后,如何仍能使该线程保持活动状态

问题是我有一个从javafx应用程序线程启动的线程,然后该线程(新线程)对文本文件执行一些读/写操作,当面对巨大的文件以进行解析时,它不会自然退出,需要花费一千七百万具体来说,行大。

我假设这是由于线程保留了我所缺少的某些资源,但是,由于我使用的是try-with-resource模型,所以我不确定这是否真的可能。

这是触发线程的javafx控制器类(使用fxml):

MainController.java:

    /**
     * This method handles what happens when the calculate button is clicked.
     * The main thing this does is disable/enable a few Nodes, as well as sparks
     * off the background thread.
     *
     * @param event
     */
    @FXML
    private void convert_button_action(ActionEvent event) {
        closing_label.setVisible(true);
        convert_button.setDisable(true);
        input_text = input_NCLocation_field.getText();
        output_text = output_Location_Field.getText();
        indicator_node.setVisible(true);

        if (!toggleSwitch.isSelected()) {
            (new Thread(new FileWriter(input_text, output_text, indicator_node))).start();
        } else {
            DateWriter temp = new DateWriter(input_text, output_text, indicator_node, yr_mn_dy.isSelected());
            (new Thread(temp)).start();
        }

    }

那里没有什么花哨的东西,只是一些使事物可见/不可见,并根据用户的输入启动适当的线程。接下来是整个Thread类,因为它不是太大。它所做的实际上只是将一行看起来像是:yearmonthday转换为year,month,day,或者如果用户单击了要求的复选框,则它将年月和日列分隔为单独的文件。只是用于用例的便捷工具。

请注意run()方法末尾的println语句。我每次都看到这个println,但是在它发生之后,什么也没有发生。程序不退出,线程不停止,什么也没有。

package File_Conversion;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javafx.application.Platform;
import javafx.scene.control.ProgressIndicator;

/**
 * This class is the background 'worker' thread that does all of the heavy duty
 * file IO for splitting up the NC file. It periodically sends reports back to
 * the main application thread to update the progress indicator.
 *
 * @author William
 */
public class DateWriter implements Runnable {

    private final ProgressIndicator myIndicator;
    private static File ncFile;
    private final String outputLocationFile;
    private float zmax, zmin, xmax, xmin, ymax, ymin;
    private ArrayList<Float> xList, yList, zList;
    private final DecimalFormat numberFormat = new DecimalFormat("#.000000");
    private final DecimalFormat numberFormatMinMax = new DecimalFormat("#.00000");
    private final boolean yr_mon_day;

    /**
     * This is the main constructor, it needs a valid NC file to continue.
     *
     * @param inputNCFile
     * @param outputLocation
     * @param myIndicator
     * @param yr_mon_day
     */
    public DateWriter(String inputNCFile, String outputLocation, ProgressIndicator myIndicator, boolean yr_mon_day) {
        this.yr_mon_day = yr_mon_day;
        this.myIndicator = myIndicator;
        ncFile = new File(inputNCFile);
        outputLocationFile = outputLocation;

    }

    /**
     * The primary run() method, starts the thread.
     */
    @Override
    public void run() {
        convertDate();
        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                File_Conversion.stage_returner().close();
            }

        });
        System.out.println("I'm at the end of the run...??");
    }

    public boolean convertDate() {

        BufferedReader br = null;
        java.io.FileWriter yearWriter = null, MonthWriter = null, DayWriter = null
                            ,fWriter = null;
        BufferedWriter yearBuf = null, monthBuf = null, dayBuf = null, writer = null;


        try {
                br = new BufferedReader(new FileReader(ncFile));
                if (yr_mon_day) {
                yearWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_year.csv", false);
                yearBuf = new BufferedWriter(yearWriter);
                MonthWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_month.csv", false);
                monthBuf = new BufferedWriter(MonthWriter);
                DayWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_day.csv", false);

                dayBuf = new BufferedWriter(DayWriter);
                String input;
                String temp;
                String temp2;
                String temp3;
                while ((input = br.readLine()) != null) {
                    temp = input.substring(0, 4);

                    temp2 = input.substring(4, 6);

                    temp3 = input.substring(6);
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            myIndicator.setProgress(-1);
                        }
                    });
                    yearBuf.write(temp + "\n");
                    monthBuf.write(temp2 + "\n");
                    dayBuf.write(temp3 + "\n");
                }

            } else {
                fWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName() + "_modified.csv", false);
                writer = new BufferedWriter(fWriter);
                String input;
                String temp;
                while ((input = br.readLine()) != null) {
                    temp = input.substring(0, 4) + "," + input.substring(4, 6) + "," + input.substring(6);
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            myIndicator.setProgress(-1);
                        }
                    });
                    writer.write(temp + "\n");
                }

            }
        } catch (IOException e) {
            e.printStackTrace(System.out);
        }finally{
            try{
                if (br!=null) br.close();
                if (yearBuf !=null) yearBuf.close();
                if (monthBuf != null)monthBuf.close();
                if (dayBuf != null)dayBuf.close();
                if (yearWriter != null)yearWriter.close();
                if (MonthWriter != null)MonthWriter.close();
                if (DayWriter != null)DayWriter.close();
                if (fWriter != null) fWriter.close();
                if (writer != null) writer.close();

            }catch(IOException e){
                e.printStackTrace(System.out);
            }
        }

        return true;
    }

}

再次,没有什么幻想,有一些缓冲的流和编写器,仅此而已!值得注意的是,这对于小型/非巨型文件非常适用。只有当面对数百万行的文件时,我才能看到这种行为。

您能提供的任何帮助将不胜感激,谢谢!

编辑1

只是为了澄清一下,if /
else的部分原因是尝试资源疯狂,而另一部分则以更传统的方式,仅是为了举例说明已经尝试了两种方法,出现了相同的症状排除了通过两个逻辑块运行的线程,因此我相当确定关闭资源的方式与此无关。


问题答案:

因此,事实证明这是一个解决方案,我对昨天有个想法,但从未采取任何行动。

从本质上讲,我遇到的问题的根源(我认为)是由于写缓冲区溢出导致的,导致未定义的行为。

现在,我不知道这是由于Java bufferedwriter的错误Java实现还是由于到底发生了什么,但是解决方案却变得相对简单:现在
每进行一次迭代就
刷新流,我知道您知道什么在想,加!经常这样!减速一定是巨大的!是的,确实如此,增速放缓是巨大的,它使解析文件的时间从大约14秒缩短到大约4分钟达到了1700万行。

可能我可以稍微提高刷新次数以提高性能,但是每10次刷新一次仍然失败。

我敢肯定,这是Java中如何处理读/写操作和内存管理的内部结果,而且我没有时间去研究它。如果有人想花时间对这种行为做出很好的解释,我会很乐意将我接受的答案切换到他们的帖子,因为它更加完整。

固定类(现在可以使用)的代码以DateWriter供将来检查:

package File_Conversion;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javafx.application.Platform;
import javafx.scene.control.ProgressIndicator;

/**
 * This class is the background 'worker' thread that does all of the heavy duty
 * file IO for splitting up the NC file. It periodically sends reports back to
 * the main application thread to update the progress indicator.
 *
 * @author William
 */
public class DateWriter implements Runnable {

    private final ProgressIndicator myIndicator;
    private static File ncFile;
    private final String outputLocationFile;
    private float zmax, zmin, xmax, xmin, ymax, ymin;
    private ArrayList<Float> xList, yList, zList;
    private final DecimalFormat numberFormat = new DecimalFormat("#.000000");
    private final DecimalFormat numberFormatMinMax = new DecimalFormat("#.00000");
    private final boolean yr_mon_day;

    /**
     * This is the main constructor, it needs a valid NC file to continue.
     *
     * @param inputNCFile
     * @param outputLocation
     * @param myIndicator
     * @param yr_mon_day
     */
    public DateWriter(String inputNCFile, String outputLocation, ProgressIndicator myIndicator, boolean yr_mon_day) {
        this.yr_mon_day = yr_mon_day;
        this.myIndicator = myIndicator;
        ncFile = new File(inputNCFile);
        outputLocationFile = outputLocation;
    }

    /**
     * The primary run() method, starts the thread.
     */
    @Override
    public void run() {
        convertDate();
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                File_Conversion.stage_returner().close();
            }
        });
        System.out.println("At the end of the method.");

    }

    public boolean convertDate() {

        BufferedReader br = null;
        java.io.FileWriter yearWriter = null, monthWriter = null, dayWriter = null, fWriter = null;
        BufferedWriter yearBuf = null, monthBuf = null, dayBuf = null, writer = null;
        try {
            br = new BufferedReader(new FileReader(ncFile));
            if (yr_mon_day) {
                yearWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_year.csv", false);
                yearBuf = new BufferedWriter(yearWriter);
                monthWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_month.csv", false);
                monthBuf = new BufferedWriter(monthWriter);
                dayWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName().substring(0, ncFile.getName().lastIndexOf(".")) + "_modified_day.csv", false);

                dayBuf = new BufferedWriter(dayWriter);
                String input;
                String temp;
                String temp2;
                String temp3;
                while ((input = br.readLine()) != null) {
                    temp = input.substring(0, 4);

                    temp2 = input.substring(4, 6);

                    temp3 = input.substring(6);
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            myIndicator.setProgress(-1);
                        }
                    });
                    yearBuf.write(temp + "\n");
                    monthBuf.write(temp2 + "\n");
                    dayBuf.write(temp3 + "\n");
                    yearBuf.flush();
                    monthBuf.flush();
                    dayBuf.flush();
                    temp = null;
                    temp2 = null;
                    temp3 = null;

                }
            } else {
                fWriter = new java.io.FileWriter(outputLocationFile + "\\" + ncFile.getName() + "_modified.csv", false);
                writer = new BufferedWriter(fWriter);
                String input;
                String temp;
                while ((input = br.readLine()) != null) {
                    temp = input.substring(0, 4) + "," + input.substring(4, 6) + "," + input.substring(6);
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            myIndicator.setProgress(-1);
                        }
                    });
                    writer.write(temp + "\n");
                    writer.flush();

                }

            }
        } catch (IOException e) {
            e.printStackTrace(System.out);
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (yearBuf != null) {
                    yearBuf.close();
                }
                if (monthBuf != null) {
                    monthBuf.close();
                }
                if (dayBuf != null) {
                    dayBuf.close();
                }
                if (yearWriter != null) {
                    yearWriter.close();
                }
                if (monthWriter != null) {
                    monthWriter.close();
                }
                if (dayWriter != null) {
                    dayWriter.close();
                }
                if (fWriter != null) {
                    fWriter.close();
                }
                if (writer != null) {
                    writer.close();
                }

            } catch (IOException e) {
                e.printStackTrace(System.out);
            }
        }
        return true;
    }

}


 类似资料:
  • 问题内容: 看一下这段代码: 通常,到达的结尾时,程序会终止。但是在此示例中,程序将打印“ main of End”,然后继续运行,因为线程仍在运行。有没有一种方法可以使线程在结束时 自动 停止,而无需使用类似的东西? 问题答案: 您正在创建的线程是独立的,并且不依赖于主线程终止。您可以使用线程。 当没有其他线程在运行时,守护进程线程将由JVM终止,它也包括一个执行主线程。

  • 线程的结束 现有问题 当内核线程终止时,会发生什么?如果就按目前的实现,我们会发现线程所执行的函数末尾会触发 Exception::InstructionPageFault 而终止,其中访问的的地址 stval = 0。 这是因为内核线程在执行完 entry_point 所指向的函数后会返回到 ra 指向的地址,而我们没有为其赋初值(初值为 0)。此时,程序就会尝试跳转到 0x0 地址,而显然它是

  • 我正在我的程序中创建一些线程。这里我使用了join方法,这样主线程就会等待我的所有线程。但是每当我运行这个程序的时候,它并没有完成,所有的信息消息都被打印出来,但是程序仍然没有顺利结束。有没有人能帮我解决这个问题呢? 下面是我的代码: 下面是DeployerThread的代码: 下面是线程转储: “CompilerThread0”后台进程Prio=3 TID=0x002E4310 NID=0x20

  • 我是Vert.x的新手,我试图创建一个简单的下载服务。 当此错误发生时,没有数据通过线路发送,我检查了浏览器和嗅探数据包TCP数据包(0字节从服务器发送到浏览器)。 唯一有效的方法是使用关闭连接,这至少关闭了keep-alive http连接,并结束浏览器请求。 我想要实现的是向客户机发回一些信息,以告知发生了错误,可能将状态代码设置为适当的错误,并可能向其添加一些细节(在状态文本或响应正文中)。

  • 问题内容: 如果我在无限循环中有一个线程,有没有办法在主程序结束时(例如,当我按 +时 )终止它? 问题答案: 检查这个问题。正确答案对如何以正确的方式终止线程有很好的解释: 是否有任何方法可以杀死Python中的线程? 要使线程在键盘中断信号(ctrl + c)上停止,您可以在退出之前捕获异常“ KeyboardInterrupt”并进行清除。像这样: 这样,您可以控制程序突然终止时的处理方式。

  • 问题内容: 我正在运行一个python脚本,它曾经可以运行(现在甚至可以在我的另一台笔记本电脑上运行),但是在我当前的计算机上却不行-我只收到错误代码: 我没有得到任何其他结果-甚至从文件开头的“打印”命令也没有得到。 我还没有找到特定的东西。我重新安装了python(2.7.9),pygame(1.9.1)甚至pycharm(首先尝试4.5,现在使用5.0-相同的结果) 有人知道该错误代码意味着