Static Listenfeld mit Threads füllen. Problem Listenlänge bleibt immer 0

Davicito

Erfahrenes Mitglied
Hallo ihr Lieben,

ich programmiere zur Zeit an einem Programm, welches personenbezogene Daten aus Lebensläufen ausließt und in ein zweidimensonales Listenfeld zwischenspeichert.
Das hat auch alles ohne Probleme funktioniert. Nun, als ich mehrere Dateien in mein Programm eingelesen habe, habe ich festgestellt, das bei vielen Dateien die Laufzeit der Suche sehr lange dauert. So habe ich damit begonnen mein Programm mit mehreren Threads zu versehen um mehr Performance zubekommen.

Hier mein minimalistischer Code zur Verdeutlichung:

Der Klasse Model werden Dateien übergeben (als File[] file) und 4 Threads erzeugt, die sich das File-Array aufteilen und abarbeiten.
Java:
public class Model {
    private File[] file = null;
    private List<List<String>> datensatzListe = new ArrayList<List<String>>();
     
    public void setFiles(File[] file){
        this.file = file;
    } 
  
    String[] dal = null;     
    public void readFile(File[] file){
        Thread t1= null, t2 = null, t3= null, t4 = null, tRest = null;
      
        // Schaue wieviele Dateien (file) übergeben wurden.     
        int v = file.length;       
        int rest = 0;
        int summe = 0;
      
        // Restwertberechnung
        rest = v%4; 
        // ist die Anzahl des Dateiaufkommen teilbar durch die Anzahl der Threats ohne Rest? 
        summe = v/4;
      
        if(0 < summe){
            File[] f1 = Arrays.copyOfRange(file, 0 , summe);
          
            t1 = new Thread(new FileTreads("1. Thread: ", f1));           
            t1.start();
          
            try {
                t1.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        if(summe <= v && summe != 0){
            File[] f2 = Arrays.copyOfRange(file, summe, 2*summe);
                      
            t2 = new Thread(new FileTreads("2. Thread: ", f2));
            t2.start();
          
            try {
                t2.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

       ...
      
        if(t1 != null && t1.getState() == Thread.State.TERMINATED)
            System.out.println("Tread Status: Thread 1 = "+t1.getState()+" Listenlänge: "+FileTreads.getdatensatzListenlengh());
        if(t2 != null && t2.getState() == Thread.State.TERMINATED)
            System.out.println("Tread Status: Thread 2 = "+t2.getState()+" Listenlänge: "+FileTreads.getdatensatzListenlengh());
        if(t3 != null && t3.getState() == Thread.State.TERMINATED)
            System.out.println("Tread Status: Thread 3 = "+t3.getState()+" Listenlänge: "+FileTreads.getdatensatzListenlengh());
        if(t4 != null && t4.getState() == Thread.State.TERMINATED)
            System.out.println("Tread Status: Thread 4 = "+t4.getState()+" Listenlänge: "+FileTreads.getdatensatzListenlengh());
        if(tRest != null && tRest.getState() == Thread.State.TERMINATED)
            System.out.println("Tread Status: Rest = "+tRest.getState()+" Listenlänge: "+FileTreads.getdatensatzListenlengh());
      
        //FileTreads t = new FileTreads();
        //System.out.println("Länge der DatensatzListe: "+FileTreads.getdatensatzListenlengh());
    }
}

In der Klasse FileThreads selber (s. wie folgt) werden durch die Klassen FileHandler und PersonalDatenInterpretor die Dateien gelesen und auf personenbezogene Daten überprüft, welche dann in einem statischen Listenfeld (List<List<String>> datensatzListe) aufbereitet werden sollen.
Die Problem was ich habe ist, das die Länge der Liste immer 0 ist, wenn ich die mir oben im Programmcode ausgeben lasse.
Vielleicht kann mir jemand helfen, da ich Threats das erste Mal verwende. Muss vielleicht die ganze Klasse static sein oder liegt es daran, dass statische Variablen nicht thread-sicher sind? Muss ich hier evtl. mit einer gesonderten Methode syncronized arbeiten?
Vielen Dank im Voraus.

Java:
public final class FileTreads implements Runnable{
    String treadName = "";
    private File[] file;
  
    // Länge des Datensatzfeldes, für die personenbezogene Daten
    private final int DAL_ARRAY_SYZE = 12;   
   
    private static final List<List<String>> datensatzListe = new ArrayList<>();

   // Dient der temporären Aufnahme eines Datensatzes (pro Datei) und wird später in das Listenobjekt datensatzListe aufgenommen
    String[] dal = null;
 
    public FileTreads(String name){      
        this.treadName = name;       
    }
  
    public FileTreads(String name, File[] file){       
        this.treadName = name;
        this.file = file;
    } 
   
  
    @Override
    public void run(){
        if(file != null){           
            FileHandler fh = new FileHandler();       
            PersonalDataInterpretor pdi = new PersonalDataInterpretor();           
            String[] tokenLines = null;          
          
            dal = new String[DAL_ARRAY_SYZE];   
          
            // Files werden einzeln übergeben
            for(int i=0; i<file.length;i++){               
              
                // Übergabe der Textzeilen aus einem Dokument
                tokenLines = fh.openFile(file[i]);
              
                // Alle Textzeilen eines Dokumentes werden nun Zeilenweise übergeben und Interpretiert
                for(String s: tokenLines){                       

                  
                 // bereinigt werden (innere Leerzeiochen bleiben bestehen). Phänomen tritt im odt-Format auf (s.o.)
                    String stringClean = s.trim();
                   
                    try{     
                        String[] tokens = stringClean.split("[\t\r\f;, ]+");         

                        // Namens-Prüfung
                        stringArrayTemp = pdi.searchFullName(tokens);
                        if(stringArrayTemp[0] != null && !stringArrayTemp[0].isEmpty())
                            dal[2] = stringArrayTemp[0]; //Nachname
                        if(stringArrayTemp[1] != null && !stringArrayTemp[1].isEmpty())
                            dal[3] = stringArrayTemp[1]; //Vorname

                        // Prüfe Geburtsdatum         
                        if((stringTemp = pdi.searchBirthday(tokens)) != null)
                            dal[4] = stringTemp;

                        //Prüfe Straßennamen         
                        if((stringTemp = pdi.searchStreet(tokens)) != null)
                            dal[5] = stringTemp;
                       ...

                    }catch(ArrayIndexOutOfBoundsException e){
                        System.err.println("Das TokenArray wurde überschritten! "+e);
                    } 
                    finally{
                        // Alle Datensätze werden nach und nach in eine 2D-Liste zusammengefügt                      
                        if(!dal[11].isEmpty())                           
                            datensatzListe.add(Arrays.asList(dal));                           
                    }   
                }                  
                  
                try{
                    Thread.sleep(50);
                }catch(Exception e){
                    System.err.println("Timerfehler "+e.getMessage());
                }
            } 
        }
        else System.err.println("Im FileThread fehlen die Dateien!");
    }   
  
   // Soll die Länge der Liste, nach außen, übergeben
    public static String getdatensatzListenlengh(){
        return String.valueOf(FileTreads.datensatzListe.size());
    }
}
 
Zuletzt bearbeitet:
Hallo,

die ArrayList ist nicht threadsafe, da sollte man eher Vector verwenden. Das ist in deinem Fall aber kein Problem, da du jedes mal auf das Ende des Threads wartest (.join()), sobald du ihn gestartet hast. Damit hast du keine Parallelität und damit wäre es egal, ob es threadsafe ist oder nicht.
Ich würde es auch nicht mit einer statischen Liste lösen, um alles zu sammeln, sondern mir eher von jedem Thread sein Ergebnis geben lassen.
Hier findest du grundlegende Beispiele was Threading angeht.
http://www.vogella.com/tutorials/JavaConcurrency/article.html

Um zu deinem Problem zu kommen, schau dir mal das hier an:
Code:
 if(!dal[11].isEmpty())                         
                            datensatzListe.add(Arrays.asList(dal));

Kann es vielleicht sein, dass dal[11] leer ist?


Viele Grüße
Sascha
 
Hi zerix,

danke für Deinen konstruktiven Beitrag. Ich habe das lösen können.
Ich habe nun eine Parallelität herstellen können und die join()-Methoden entfernt. Dafür musste ich natürlich eine Setter-Methode erstellen, damit alle nicht syncronen Threats ihre Ergebnisse in mein Array (in der Model) befüllen können (threat-save). Eine zusätzliche, globale Thread-Methode (in meiner Controller-Klasse) ließt alle 2 sec. lang das Array aus und überführt dann den Inhalt meines Arrays an meine View.
Damit funktioniert alles so, wie ich mir das vorerst erhoft habe. ;)

Beste Grüße!
 
Zurück