Προς το περιεχόμενο

JAVA 2 concurrent threads μέσα σε loop


Sadako

Προτεινόμενες αναρτήσεις

Καλησπέρα..

 

Δουλεύω πάνω σε μια εφαρμογή java, αλλά επειδή δεν έχω δουλέψει πολύ με threads, έχω κολλήσει σε ένα σημείο και το πρόγραμμα μου πετάει runtime exception. Το θέμα είναι, ότι δεν ξέρω αν είναι θέμα σωστής διαχείρησης των threads (synchronization βασικά) ή θέμα χρήσης του συγκεκριμένου API, γιατί κι αυτό το χρησιμοποιώ για πρώτη φορά.. Θα εκτιμούσα πολύ αν μπορούσε κάποιος να με βοηθήσει τουλάχιστον να σιγουρευτώ ότι δεν είναι θέμα threads..

 

Λοιπόν, το θέμα έχει ως εξής. Αυτό που θέλω να κάνω με λίγα λόγια, είναι 2 threads να εκτελούνται ταυτόχρονα (για να είμαι πιο ακριβής το ένα απο τα δυο threads να αρχίσει να εκτελείται απο το δεύτερο iteration και μετά αλλά αυτό ρυθμίζεται εύκολα μέσα απο έναν counter) μέσα σε ένα endless loop, το οποίο διακόπτεται απο μια boolean μεταβλητή που ορίζεται απο ενα απλό interface 2 κουμπιών (start & stop) μέσα απο JFrame.. Απλά στο τέλος κάθε iteration, απο ότι κατάλαβα είναι προτιμότερο να τερματίζονται και τα δύο threads και να ξαναδημιουργούνται στο επόμενο iteration. Τις δύο thread classes τις έχω ορίσει σαν inner classes (έχω ακολουθήσει τον τρόπο απο ένα tutorial που είχα βρει και δούλεψα πάνω του) σαν subclasses της Thread class, και μέσα έχω την run() method.

 

Με λίγα λόγια, το ΓΕΝΙΚΟ structure της εφαρμογής έχει ως εξής:

 


public class kyria_class extends JFrame
{


boolean running = false;
int counter = 1;


public static void main(String args[])
{
new kyria_class();
}


//constructor
public kyria_class()
{
//edw vazw ton kwdika gia ta κουμπιά και βάζω τις initial states
...

/*Κάνω register anonymous listeners και το addActionListener
και βάζω όταν πατάω το start απλά να εκτελείται η μοναδική μέθοδος του προγράμματος (ας την πω εδώ πχ Start_run(), ενώ όταν πατάω το stop να τίθεται πάλι η running = false.. Κάνω και set Layout Κλπ και το interface είναι έτοιμο */

}


void Start_run()
{
running = true;

//το endless loop που ανέφερα
while(running)
{
Thread thread1 = new Thread(new thread1());
Thread thread2 = new Thread(new thread2());

thread1.start();

if(counter>1) //όπως είπα θέλω το δεύτερο thread να αρχίσει απο το 2ο iteration
{
thread2.start();
}

thread1.stop();
thread2.stop();

counter++
}

}

//inner thread classes
class thread1 extends Thread
{
public void run()
{
...
}
}

class thread2 extends Thread
{
public void run()
{
...
}
}
}
[/Code]

 

Το θέμα είναι, ότι σε κάθε iteration του loop, η δουλειά που έκτελείται σε κάθε ένα απο τα threads είναι πεπερασμένης διάρκειας. Δηλαδή βάζω να επεξεργαστούν συγκεκριμένο αριθμό απο bytes of data. Οπότε στο τέλος κάθε iteration, θέλω να τερματίζονται και να αρχίζουν απο την αρχή στο επόμενο. Το κάνω αυτό λοιπόν, και ενώ κάνει compile ok, μου πετάει μια ωραιότατη (και ΤΕΡΑΣΤΙΑ)exception

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

με ένα κατεβατό απο κάτω που αραδιάζει από javax.swing.AbractButton.fireActionPerformed,

javax.awt.Component.processEvent,

javax.awt.Container.processEvent

και δεν συμμαζεύεται..

 

βοήθεια κανείς???

 

ΥΓ. Παράλληλα, επειδή κάπου αλλού συνάντησα κάτι για Daemon Threads, μπορεί να μου πει κανείς με απλά ελληνικά τι ακριβώς είναι και σε τι διαφέρουν απο τα άλλα τα user threads? Πέρα ότι ορίζονται με το setDaemon(true), ποια η διαφορά στον τρόπο που δουλεύουν μέσα στο πρόγραμμα??

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μας ανεβάζεις ολόκληρο τον κώδικα?

Γιατί έτσι δεν φαίνεται κάτι λάθος!

 

Πάντως έχω μία ένσταση για το αν θα πρέπει να τερματίζεις τα Thread σε κάθε loop.Δεν υπάρχει νομίζω λόγος και καθυστερείς και τον χρόνο εκτέλεσης κατά πολύ.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ολόκληρο τον κώδικά μου δε θέλω να τον ανεβάσω, γιατί αποτελεί κομμάτι της διπλωματικής μου. Απο χτες που πόσταρα το θέμα και μετά, διαπίστωσα ότι η NullPointerException δεν έχει να κάνει με τα threads και τη διόρθωσα.

 

Το πρόβλημα όμως με τα threads παραμένει. Βασικά αυτό που θέλω, είναι στην αρχή κάθε iteration του loop να δημιουργείται μια instance απο τα 2 threads, να εκτελούνται ταυτόχρονα οι run() και των 2 threads ώς το τέλος, και μετά να τερματίζονται για να δημιουργούνται πάλι απο την αρχή..

 

Ή τέλος πάντων δεν ξέρω αν υπάρχει τρόπος αντί να τα τερματίζω στο τέλος της run, να τους κάνω κάτι σαν "reset" και να επαναχρησιμοποιούνται απο την αρχή στο επόμενο iteration..

 

Αυτό που θέλω να κάνω, έχει να κάνει με επεξεργασία ήχου μέσα απο το java sound api (με το οποίο δε μπόρεσα να βρω βοήθεια για real-time processing σε ολόκληρο το πανεπιστήμιο, αλλά τέλος πάντων, τώρα δε μου μένει και πολύς χρόνος, οπότε απλά είπα μπας και βγάλω μόνος μου κάτι που σκέφτηκα). Το ένα thread έχει να κάνει με capture ήχου και το άλλο με playback ήχου. Θέλω όμως να γίνονται ταυτόχρονα και τα 2. Με λίγα λόγια, απο τη στιγμή που μπαίνει στο loop,

 

iteration

1 capture chunk A

2 capture chunk B play chunk A

3 capture chunk C play chunk B

4 capture chunk D play chunk C

...

κ.ο.κ

 

Κι επειδή δοκιμάζω έναν τρόπο κατα τον οποίο κάθε διαδικασία capture ή playback είναι κατά μια έννοια αυτοτελής (δηλαδή στο τέλος κάθε capture αποθηκεύεται το audio data σε ένα object στη μνήμη το οποίο παίρνει και παίζει το play thread του ΕΠΟΜΕΝΟΥ iteration), σκέφτηκα να κάνω και τα threads "αυτοτελή" μέσα σε κάθε iteration. Μπορεί να μη δουλεύει ομαλά, αλλά απο το ολότελα, θα έχω κάτι να γράψω και να σχολιάσω το γιατί ΔΕΝ δούλεψε καλά...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Είμαι τελείως άσχετος στη java αλλά μήπως το exception προκαλείται στη γραμμή thread2.start() όταν το thread2 δεν έχει ξεκινήσει (δηλαδή απόπειρα τερματισμού όταν το counter δεν είναι παραπάνω από ένα);

 

Κατά τα άλλα δεν θα έπρεπε να γνωρίζεις που ακριβώς προκαλείται το exception;

Επίσης νομίζω θα βοηθούσε αν ανέφερες ολόκληρο το stack trace του exception (αυτά τα "και δεν συμμαζεύεται.."), φυσικά κάποιον που μπορεί να το διαβάσει, όχι εμένα :D

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Θα μπορούσα να σε βοηθήσω αλλά επειδή όπως γνωρίζεις στον προγραμματισμό όλα είναι πιθανά,πρέπει να δω όλο τον κώδικα γιατί προφανώς υπάρχει κάποιο λάθος σε κάποιο σημείο που δεν έχεις postάρει....

 

Τώρα όσο αναφορά το θέμα των Thread...πιστεύω καλύτερα είναι να βάλεις ένα loop while(true){} μέσα στο κάθε Thread.Και όταν πατιέται το κουμπί stop να κάνεις Thread.stop();.Έτσι θα πετύχεις καλύτερη ταχύτητα εκτέλεσης καθώς όπως ξαναείπα η εκκίνηση και ο τερματισμός των Thread παίρνει κάποιο χρόνο που μπορεί να αποβεί και μοιραίος για κάποιες real-time εφαρμογές.

 

Τώρα μία ιδέα: Προφανώς κάνεις με μία συχνότητα το capture του ήχου όπως και με μία συχνότητα play το audio.Οπότε εγώ στο τέλος κάθε Thread θα έβαζα ένα Thread.sleep(miliseconds) μέχρι την επόμενη δειγματοληψία.Έτσι θα υπάρχει και χρόνος για το play Thread να παίξει τον ήχο,αλλά και δεν θα δουλεύει η cpu στο 100%.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καταρχάς χειρίζεσαι λάθος τα threads. Ο "σωστός" (βλ. απόλυτα ασφαλής) τρόπος είναι:

 

>
class MyThread extends Thread {
 private boolean run;

 MyThread() { run=true; }

 synchronized public void stopThread() { run = false; }

 synchronized private boolean isRunning() { return run; }

 public void run() {
   while (isRunning()) {
     // do work
   }
 }
}

 

Ουσιαστικά, μέσα στην while θέλεις τις αντίστοιχες εντολές που θα παίρνουν τα δεδομένα από έναν τοπικό buffer και θα τα επεξεργάζονται. Μπορείς να βάζεις το thread σε αναμονή με την wait() και να το ξυπνάς με την notify().

 

Όσον αφορά τα daemon threads, αν έχουν απομείνει μόνον daemon threads προς εκτέλεση, τότε η JVM τα σταματά και ολοκληρώνει την εκτέλεση της εφαρμογής. Αν από την άλλη έχει απομείνει έστω και ένα non-daemon thread (και ας έχει τελειώσει η main() ) τότε δεν θα σταματήσει η εκτέλεση της JVM.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...