java:concurrency_intro

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
java:concurrency_intro [2015/03/24 13:24]
gthanos [Επανενεργοποίηση ενός νήματος μέσω της μεθόδου interrupt()]
java:concurrency_intro [2016/02/26 11:15] (current)
Line 86: Line 86:
   }   }
 </​code>​ </​code>​
 +
 +Εάν ένα νήμα δεν καλεί κάποια μέθοδο που δημιουργεί [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​InterruptedException.html|InterruptedException]] και η εφαρμογή δουλεύει με interrupts, θα πρέπει περιοδικά να ελέγχει κατά πόσο υπάρχει κάποια σήμα διακοπής προς το συγκεκριμένο νήμα σε μία ανακύκλωση της μορφής
 +
 +<code java>
 +for (int i = 0; i < inputs.length;​ i++) {
 +    heavyCalc(inputs[i]);​
 +    if (Thread.interrupted()) {
 +        throw new InterruptedException();​
 +    }
 +}
 +</​code>​
 +
 +<WRAP center round 85% tip>
 +Ο μηχανισμός διακοπής υλοποιείται χρησιμοποιώντας ένα εσωτερικό flag (boolean true/false) γνωστό ως interrupt status. H κλήση της Thread.interrupt() θέτει στην τιμή true αυτό το flag. Κάθε φορά που ένα νήμα ελέγχει αν έχει διακοπεί ή όχι (καλώντας τη στατική μέθοδο Thread.interrupted() ), το παραπάνω flag απενεργοποιείται λαμβάνοντας την τιμή false. ​
 +
 +Η μη στατική μέθοδος isInterrupted(),​ χρησιμοποιείται από ένα νήμα για να ενημερωθεί για την κατάσταση διακοπής του ιδίου νήματος ή ενός άλλου νήματος (εξαρτάται από το αντικείμενο που την καλεί),​ αλλά δεν αλλάζει την κατάσταση του flag διακοπής.
 +</​WRAP>​
 +
 +===== Περιμένοντας ένα νήμα να ολοκληρώσει μέσω της μεθόδου join() =====
 +
 +Η μέθοδος [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Thread.html#​join()|join()]] επιτρέπει σε ένα νήμα να σταματήσει την εκτέλεση του έως ότου ένα άλλο νήμα να ολοκληρώσει την εκτέλεση του. Αν υποθέσουμε ότι ένα νήμα '​t'​ εκτελείται παράλληλα με το τρέχον νήμα, εάν το τρέχον νήμα καλέσει το παρακάτω
 +
 +<code java>
 +  t.join();
 +</​code>​
 +
 +τότε η εκτέλεση του σταματάει έως ότου το νήμα **'​t'​** να τερματίσει την εκτέλεση του. Υπάρχουν οι εξής παραλλαγές της μεθόδου join
 +  * **t.join():​** περίμενε μέχρι το νήμα t να τερματίσει
 +  * **t.join(long millis):** μέχρι το νήμα t να τερματίσει ή περίμενε για **millis** milliseconds.
 +  * **t.join(long millis, int nanos):** μέχρι το νήμα t να τερματίσει ή περίμενε για **millis+nanos/​1000000** milliseconds.
 +
 +Όπως και η μέθοδος **sleep()** η μέθοδος **join()** δύναται να διακοπεί από ένα [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​InterruptedException.html|InterruptedException()]].
 +
 +===== Εφαρμόζοντας τις μεθόδους sleep()/​interrupt()/​join() σε ένα παράδειγμα =====
 +
 +Δείτε το παρακάτω παράδειγμα εκτέλεσης δύο νημάτων,​ το οποίο χρησιμοποιεί τις μεθόδους sleep(), interrupt() και join(). Το κεντρικό νήμα (μέθοδος main) περιμένει το νήμα που δημιουργείται για δεδομένο χρονικό διάστημα. Κάθε 1 δευτερόλεπτο το κεντρικό νήμα επιστρέφει από την μέθοδο **join(1000)** και εξετάζει εάν a)ο χρόνος εκτέλεσης του ολοκληρώθηκε και b) το παιδί τελείωσε μέσω της **t.isAlive()**. Εάν ισχύουν και οι δύο παραπάνω προϋποθέσεις τότε στέλνει ένα interrupt στο παιδί και περιμένει έως ότου αυτό να τερματίσει μέσω της **t.join()**. Στην συνέχεια ολοκληρώνει και το κεντρικό νήμα την εκτέλεση του.
 +
 +<code java MessageLoops.java>​
 +public class MessageLoop implements Runnable {
 +  public void run() {
 +    String importantInfo[] = {
 +      "Mares eat oats",
 +      "Does eat oats",
 +      "​Little lambs eat ivy",
 +      "A kid will eat ivy too"
 +    };
 +    try {
 +      for (int i = 0;
 +        i < importantInfo.length;​
 +        i++) {
 +        // Pause for 4 seconds
 +        Thread.sleep(4000);​
 +        // Print a message
 +        SimpleThreads.threadMessage(importantInfo[i]);​
 +      }
 +    } catch (InterruptedException e) {
 +      SimpleThreads.threadMessage("​I wasn't done!"​);​
 +    }
 +  }
 +}
 +</​code>​
 +
 +<code java SimpleThreads.java>​
 +public class SimpleThreads {
 +
 +  // Display a message, preceded by
 +  // the name of the current thread
 +  public static void threadMessage(String message) {
 +    String threadName =
 +      Thread.currentThread().getName();​
 +    System.out.format("​%s:​ %s%n",
 +              threadName,
 +              message);
 +  }  ​
 +
 +  public static void main(String args[])
 +    throws InterruptedException {
 +
 +    // Delay, in milliseconds before
 +    // we interrupt MessageLoop
 +    // thread (default one hour).
 +    long patience = 1000 * 60 * 60;
 +
 +    // If command line argument
 +    // present, gives patience
 +    // in seconds.
 +    if (args.length > 0) {
 +      try {
 +        patience = Long.parseLong(args[0]) * 1000;
 +      } catch (NumberFormatException e) {
 +        System.err.println("​Argument must be an integer."​);​
 +        System.exit(1);​
 +      }
 +    }
 +
 +    threadMessage("​Starting MessageLoop thread"​);​
 +    long startTime = System.currentTimeMillis();​
 +    Thread t = new Thread(new MessageLoop());​
 +    t.start();
 +
 +    threadMessage("​Waiting for MessageLoop thread to finish"​);​
 +    // loop until MessageLoop
 +    // thread exits
 +    while (t.isAlive()) {
 +      threadMessage("​Still waiting..."​);​
 +      // Wait maximum of 1 second
 +      // for MessageLoop thread
 +      // to finish.
 +      t.join(1000);​
 +      if (((System.currentTimeMillis() - startTime) > patience)
 +          && t.isAlive()) {
 +        threadMessage("​Tired of waiting!"​);​
 +        t.interrupt();​
 +        // Shouldn'​t be long now
 +        // -- wait indefinitely
 +        t.join();
 +      }
 +    }
 +    threadMessage("​Finally!"​);​
 +  }
 +}</​code>​
 +
  
  
java/concurrency_intro.1427203443.txt.gz · Last modified: 2016/02/26 11:15 (external edit)