[英]field goes out of scope java
我對多線程應用程序有一些問題。 我想從類似CSV的文件中加載數據,並將其存儲在緩沖區中以供以后檢索。
似乎當線程結束(?)時動物列表超出范圍了,我不了解Java線程的某些知識,將不勝感激。
調用方式:
ParseCSV parser = new ParseCSV(null);
EventQueue.invokeLater(parser);
System.err.println("printing!");
編輯-根據要求,這是失敗的部分-praser緩沖區的內容此時為空。 我以為如果我在解析器中使用new關鍵字,動物的內容將是持久的。
while(parser.hasNext()){
System.err.println("#");
System.err.println(parser.getNext().toString());
}
解析器類:
public class ParseCSV implements Runnable{
private String path = null;
private File file = null;
private static Logger log = LogManager.getLogger(ParseCSV.class.getName());
private volatile ArrayList<Animal> animals = new ArrayList<Animal>();
private int pointer =0;
public ParseCSV(String path) {
animals = new ArrayList<Animal>(); //tried to reinitialize, didn't help this is where the problem occurs
if(path == null){
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(null);
file = jfc.getSelectedFile();
this.path = file.getAbsolutePath();
}
else {
this.path = path;
}
log.debug("Initialized file parser for " + this.path);
}
@Override
public void run() {
log.debug("begining file parse");
System.err.println("runnner");
try {
Scanner fileScan = new Scanner(this.file);
while(fileScan.hasNextLine()){
parseLine(fileScan.nextLine());
}
fileScan.close();
} catch (FileNotFoundException e) {
log.error("Exception occured: " + e.getMessage() + "\nstack:\n" + e.getStackTrace());
System.err.println("Exception: " + e.getMessage());
e.printStackTrace();
}
}
private void parseLine(String nextLine) {
Scanner lineScanner = new Scanner(nextLine);
lineScanner.useDelimiter("\\s\\|\\s");
if(lineScanner.hasNext()){
Animal an = new Animal(lineScanner.next(), //person
lineScanner.next(), //animal
Integer.parseInt(lineScanner.next()), //emp-number
lineScanner.next(), //date
Integer.parseInt(lineScanner.next()), //ani-number
lineScanner.next());
animals.add(an); //contract ID
System.err.println(an.toString()); //prints correct result!
}
lineScanner.close();
}
public String getPath() { return path; }
public void setPath(String path) { this.path = path; }
public boolean hasNext(){
System.err.println("size of data = " + animals.size());
if(animals.size() == pointer || animals.isEmpty()) return false;
else return true;
}
public Sale getNext(){
if(animals.size() == pointer) return null;
return animals.get(pointer++);
}
}
編輯-添加注釋以指出問題出現的位置
您需要等待解析器線程完成(當前兩者同時發生),這可能是程序不打印任何內容的原因。 您可以嘗試添加一些日志記錄語句,然后檢查序列是否正確。
EventQueue#invokeLater
將任務添加到事件隊列中,因此在進入下一行時可能無法完成。 請改用EventQueue#invokeAndWait
,它等待任務完成。
您的代碼有一些問題。 其中一些實際上導致了問題,而另一些只是表明您並不真正了解自己要做什么。
private volatile ArrayList<Animal> animals = new ArrayList<Animal>();
為什么在此上使用volatile? 每個線程都有自己的動物列表,因此它們僅由一個線程使用。 如果您的主類具有每個人都添加的動物模型,則需要使其具有可變性,因為多個線程可以訪問它。
animals = new ArrayList<Animal>(); //tried to reinitialize, didn't help this is where the problem occurs
這不會改變任何東西。 如果您認為該方法可以多次調用並且每次都想要一個新列表,則可能會很有用,但是這可能只是浪費。
現在到真正的問題:
調用線程時,是因為您希望它在后台運行,而不是停止主程序執行。 然后,您可以在實際完成的某個時間返回結果。 正如人們所說的,如果您只想要一個新線程而又不真正在后台運行,則可以執行EventQueue#invokeAndWait,但對於您而言,這不是解決方案。
您可以使用觀察者模式。 為此,您需要創建一個具有notify方法的接口(將其稱為parseListner或其他名稱)。 解析器具有parseListerners的列表。 解析器完成解析后,它會告訴所有偵聽器(通過在接口上調用方法)。 因此,您最終得到的是這樣的代碼:
public interface ParseListner{
void fileParsed(String fileName, List<Animal> animals);
}
public class Main implements ParseListner{
public void main(){
ParseCSV parser = new ParseCSV(this);
EventQueue.invokeLater(filePath, parser);
}
public void fileParsed(String fileName, List<Animal> animals){
System.Out.Println(doneParsing);
}
}
公共類ParseCSV實現Runnable {List listners = new ArrayList <>(); 公共ParseCSV(字符串路徑,ParseListner調用方){listner.add(caller)}
@Override
public void run() {
//all the parsestuff
for(ParseListner p : listners)
p.parsedFile(fileName, animals);
}
我使用了一個列表,因為它幾乎總是有用的(因此完成后您可以做很多事情)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.