Threads nacheinander ausführen

Joey85

Mitglied
Hallo,

ich habe folgendes Problem: Ich baue mir gerade mit Netbeans eine GUI. Ich habe verschiedene Threads die durch einen click auf einen bestimmten button ausgeführt werden.
Bsp.:

privat class a extends Thread {
public void run(){
dosomething;
}
}

private doActionPerformed(){
a a1 = new a();
a1.start();
}

Jetzt will ich bei einem button aber, dass mehrere threads hintereinander ausgeführt werden. Zur zeit werden alle parallel ausgeführt, was aber nicht sein soll.

private doActionPerformed(){
a a1 = new a();
a1.start();
b b1 = new b();
b1.start();
usw...
}

Wie kriege ich es hin, dass erst gewartet wird bis a ausgeführt wird und dann erst b?
 
Java-Code bitte in JAVA-Tags schreiben!

Verwende die Methode
Code:
join()
die dir Thread anbietet
 
Das habe ich probiert. Jedoch besteht der Anfang eines Threads bei mir immer aus einem Dialog. Wenn ich join benutze ist das Dialogfenster komplett weiß und ich kann nix machen.
 
Jap weil sich Thread und GUI-Thread hier in die Quere kommen.
Der GUI-Thread und dein Thread sollten unabhängig von einander laufen!
Stichwort: SwingWorker with Thread
 
OK. Die threads sollen seriell laufen.
Java:
public class normalization extends Thread {

               public void run() {
            
            File[] file = FileChooser_txt.getSelectedFiles();
            if (file.length == 0) {
                Text1.setText("No file loaded.");
            } else if (file.length == 1) {
                String[] pfad = {file[0].getAbsolutePath().replace("\\", "/")};
                String name = file[0].getName().substring(0, file[0].getName().lastIndexOf(46));
                File normalize = new File(file[0].getParent(), name + "_normalized.txt");
                String[] newfile = {normalize.getAbsolutePath().replace("\\", "/")};

                String[] methods = {"mean", "first", "none"};
                String[] transformation = {"none", "log"};

                JComboBox box1 = new JComboBox(methods);
                JComboBox box2 = new JComboBox(transformation);

                Object[] message = {"Method of normalization: ", box1, "Transformation: ", box2};
                int resp = JOptionPane.showConfirmDialog(null, message, "Parameters of the normalization",
                        JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);

                if (resp == JOptionPane.OK_OPTION) {
                    String method = (String) box1.getSelectedItem();
                    String transform = (String) box2.getSelectedItem();
                    final ProgressMonitor pbar = new ProgressMonitor(monitor, "Normalization...",
                            "Waiting...", 0, 100);
                    monitor.setVisible(true);
                    String[] meth = {method};
                    String[] trans = {transform};
                    
                    if (meth[0] == null || trans[0] == null) {
                        //  Text2.setText("Aborted by user.");
                    } else {
                        double counter = 1.0;
                        .....
                        double percent = (counter / (double) file.length) * 100;
                        pbar.setProgress((int) percent);
                        pbar.setNote("Operation is " + (int) percent + "% complete");
                        if (pbar.isCanceled()) {
                            pbar.close();
                            monitor.setVisible(false);
                            //System.exit(1);
                            return;
                        }
                    }
                    File neu = new File(newfile[0].replace("\\", "/"));
                    if (neu.exists()) {
                        Text2.setText("Normalized values of " + name + " saved at: " + newfile[0].replace  ("\\", "/"));

                    } else {
                        Text2.setText("Error. Normalization failed. Check your input data.");
                    }
                } else {
                    Text2.setText("Normalization aborted by user.");
                }
                monitor.setVisible(false);            
        }
    }


public class something extends Thread {

               public void run() {
            File[] file = FileChooser_txt.getSelectedFiles();
            if (file.length == 0) {
                Text1.setText("No file loaded.");
            } else if (file.length == 1) {
                String[] pfad = {file[0].getAbsolutePath().replace("\\", "/")};
                String name = file[0].getName().substring(0, file[0].getName().lastIndexOf(46));
                File normalize = new File(file[0].getParent(), name + "_normalized.txt");
                String[] newfile = {normalize.getAbsolutePath().replace("\\", "/")};

                String[] methods = {"mean", "first", "none"};
                String[] transformation = {"none", "log"};

                JComboBox box1 = new JComboBox(methods);
                JComboBox box2 = new JComboBox(transformation);
                ......
      }
   }
}


private void Automated1ActionPerformed(java.awt.event.ActionEvent evt) {
                normalization norm = new normalization();
                norm.start();
                try {
                   norm.join();
               } catch (InterruptedException ex) {
                    Logger.getLogger(CyBar2.class.getName()).log(Level.SEVERE, null, ex);
                }

                something some = new something();
                some.start();

                try {

                some.join();
                } catch (InterruptedException ex) {
                    Logger.getLogger(CyBar2.class.getName()).log(Level.SEVERE, null, ex);
               }
}

Ich habe gerade probiert den GUI-Teil in der AutomatedActionPerformed-Methode zu lassen und dann die Parameter dem Thread zu übergeben. Wenn ich allerdings norm.start(mit parameter) aufrufe, geht die public void run()-Methode nichtmehr. norm.run(mit parameter) würde gehen, allerdings ist die GUI dann eingefroren.
 
Ich habe gerade probiert den GUI-Teil in der AutomatedActionPerformed-Methode zu lassen und dann die Parameter dem Thread zu übergeben. Wenn ich allerdings norm.start(mit parameter) aufrufe, geht die public void run()-Methode nichtmehr. norm.run(mit parameter) würde gehen, allerdings ist die GUI dann eingefroren.

Passt, getrennt sollten sie auch sein!
Wie oben schon gesagt
Jap weil sich Thread und GUI-Thread hier in die Quere kommen.
lösen nähere Infos dazu findest du hier (Stichworte: Java EDT, SwingWorker, GUI blocked)

Dadurch das du
Code:
run
direkt aufrufst blockiert dieser solange alle Aktionen die die GUI aktualisieren sollen (auch window resize etc.) daher musst du deinen gewünschten Thread unabhängig vom GUI Thread laufen lassen.
 
Code:
start()
führt eine vorhandene
Code:
run()
Methode aus. Da deine aber nun Parameter erwartet, findet
Code:
start()
nichts zum Ausführen!

Setze deine Parameter über setter Methoden und rufe dann ganz normal
Code:
start()
auf.
(Und die Parameter der run Methode musst du natürlich wieder entfernen
 
Zuletzt bearbeitet:
Hab das jetzt per setter und getter Methoden gelöst. Leider bleibt die GUI immernoch hängen.

Java:
private class  normalization extends Thread {
        String[] pfad;
        String[] newfile;
        String[] meth;
        String[] trans;
        
        public void setpfad(String[] name){
         pfad=name;
     }
        public String[] getpfad(){
         return pfad;
        }
....
}

 private void NormalizeActionPerformed(java.awt.event.ActionEvent evt) {                                          
        // TODO add your handling code here:
        File[] file = FileChooser_txt.getSelectedFiles();

            if (file.length == 0) {
                Text1.setText("No file loaded.");
            } else if (file.length == 1) {
                String[] pfad= {file[0].getAbsolutePath().replace("\\", "/")};
                
                //System.err.println(file[0].getName().lastIndexOf("."));
                String name = file[0].getName().substring(0, file[0].getName().lastIndexOf(46));
                //System.err.println(name);
                File normalize = new File(file[0].getParent(), name + "_normalized.txt");
                String[] newfile= {normalize.getAbsolutePath().replace("\\", "/")};
                System.out.println(newfile[0]);

                String[] methods = {"mean", "first", "none"};
                String[] transformation = {"none", "log"};

                JComboBox box1 = new JComboBox(methods);
                JComboBox box2 = new JComboBox(transformation);

                Object[] message = {"Method of normalization: ", box1, "Transformation: ", box2};
                int resp = JOptionPane.showConfirmDialog(null, message, "Parameters of the normalization",
                        JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);

                if (resp == JOptionPane.OK_OPTION) {
                    String method = (String) box1.getSelectedItem();
                    String transform = (String) box2.getSelectedItem();
                   // final ProgressMonitor pbar = new ProgressMonitor(monitor, "Normalization...",
                    //        "Waiting...", 0, 100);
                   // monitor.setVisible(true);
                    String[] meth = {method};
                    String[] trans= {transform};
                    
                   normalization norm = new normalization();
                   norm.setpfad(pfad);
                   norm.setnew(newfile);
                   norm.settrans(trans);
                   norm.setmeth(meth);
                   norm.start();
                    try {
                        norm.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(CyBar2.class.getName()).log(Level.SEVERE, null, ex);
                    }
         
                } 
....
}
}
 
Java:
                   normalization norm = new normalization();
                   norm.setpfad(pfad);
                   norm.setnew(newfile);
                   norm.settrans(trans);
                   norm.setmeth(meth);
                   norm.start();
                    try {
                        norm.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(CyBar2.class.getName()).log(Level.SEVERE, null, ex);
                    }

1. Klassennamen schreibt man immer groß -> UpperCamelCase

2. Dein Thread blockiert noch immer den GUI Thread (Stichwort EDT Thread). Daher kann deine GUI solange nicht reagieren und etwas machen solange dein Thread rennt.
 
Ja finden tu ich da viel, verstehen allerdings nicht 🙁. Was müsste ich an meinem code noch ändern, damit der thread im Hintergrund ausgeführt wird und nicht die GUI blockiert?
 
Nein so nicht. Lies dir entsprechende Themen durch, teste mal in einem simplen Beispiel. Solltest du etwas nicht verstehen dann frage danach (inkl Code).
Einfach nach der Lösung fragen sieht hier keiner gerne.
 
OK. Also ist es erstmal richtig, dass ich die Klasse Thread dabei nicht benötige, sondern stattdessen die Klasse SwingWorker? Ich kann einfach nicht unterscheiden, was in den GUI-Teil alles reinkommt und was in den eigentlichen berechnenden thread.

Nachtrag:

Habs jetzt hinbekommen. Habs wiefolgt geändert:
Java:
class  Normalization extends SwingWorker<Integer,Integer> {
      
        String[] pfad;
        String[] newfile;
        String[] meth;
        String[] trans;
        
        public void setpfad(String[] name){
         pfad=name;
     }
        public String[] getpfad(){
         return pfad;
        }
        
           public void setnew(String[] newpath){
           newfile=newpath;
     }
        public String[] getnew(){
         return newfile;
        }
        
              public void setmeth(String[] method){
         meth=method;
     }
        public String[] getmeth(){
         return meth;
        }
        
           public void settrans(String[] transform){
           trans=transform;
     }
        public String[] gettrans(){
         return trans;
        }
        

          protected Integer doInBackground() throws Exception{
          .....
           return 42;
    }
}

private void NormalizeActionPerformed(java.awt.event.ActionEvent evt) {                                          
        // TODO add your handling code here:
        File[] file = FileChooser_txt.getSelectedFiles();
              System.out.println(file.length);
            if (file.length == 0) {
                Text1.setText("No file loaded.");
            } else if (file.length == 1) {
                String[] pfad= {file[0].getAbsolutePath().replace("\\", "/")};
                
                //System.err.println(file[0].getName().lastIndexOf("."));
                String name = file[0].getName().substring(0, file[0].getName().lastIndexOf(46));
                //System.err.println(name);
                File normalize = new File(file[0].getParent(), name + "_normalized.txt");
                String[] newfile= {normalize.getAbsolutePath().replace("\\", "/")};
                System.out.println(newfile[0]);

                String[] methods = {"mean", "first", "none"};
                String[] transformation = {"none", "log"};

                JComboBox box1 = new JComboBox(methods);
                JComboBox box2 = new JComboBox(transformation);

                Object[] message = {"Method of normalization: ", box1, "Transformation: ", box2};
                int resp = JOptionPane.showConfirmDialog(null, message, "Parameters of the normalization",
                        JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);

                if (resp == JOptionPane.OK_OPTION) {
                    String method = (String) box1.getSelectedItem();
                    String transform = (String) box2.getSelectedItem();
                    String[] meth = {method};
                    String[] trans= {transform};
                    
                   Normalization norm = new Normalization();
                   norm.setpfad(pfad);
                   norm.setnew(newfile);
                   norm.settrans(trans);
                   norm.setmeth(meth);
                  // norm.start();
                   norm.execute();
                   ....
 }
}

Meine Frage lediglich: Muss die Methode doinBackground() immer einen Rückgabetyp haben? Void scheint nicht zu funktionieren.
 
Zuletzt bearbeitet:
OK hab jetzt den Rückgabetyp auf Void. Jetzt will ich eine ProgressBar erzeugen, die mir den Fortschritt anzeigt.
Initialisiert hab ich sie im GUI-Thread so:
Java:
double counter = 1.0;
final ProgressMonitor pbar = new ProgressMonitor(monitor, "Normalization...",
"Waiting...", 0, 100);
monitor.setVisible(true);
Der Counter wird bei jedem Schleifendurchgang um 1 erhöht und durch die Anzahl der Dateien geteilt, dann der Wert der ProgressBar auf diesen Wert gesetzt.

Java:
double percent = (counter / (double) file.length) * 100;
                        pbar.setProgress((int) percent);
                        pbar.setNote("Operation is " + (int) percent + "% complete");
                        if (pbar.isCanceled()) {
                            pbar.close();
                            monitor.setVisible(false);
                            return;
                            
                        }

Wie kann ich es anstellen, dass die ProgessBar durch den SwingWorker aktualisiert wird, wenn der thread abgearbeitet wurde?
 
Gut, scheint soweit zu funktionieren.
Jedoch ist mir was aufgefallen:
Ich übergebe dem thread den Counter, um den Progress berechnen zu können. Allerdings ist es irgendwie so, dass der thread nicht in chronologischer Abfolge arbeitet sondern durcheinander. Lasse ich mir den Counter ausgeben sieht das beispielsweise so aus: 1,2,4,5,3,8,6,9,7,10.
Dadurch läuft die ProgressBar natürlich nicht richtig und endet zB bei 85%, wodurch sie sich nicht schliesst am Ende. Wie kann ich also gewährleisten, dass die threads richtig abgearbeitet werden?
 

Zurück
Oben