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:19]
gthanos [Σταματώντας την εκτέλεση ενός νήματος μέσω της μεθόδου sleep()]
java:concurrency_intro [2016/02/26 11:15] (current)
Line 76: Line 76:
 ===== Επανενεργοποίηση ενός νήματος μέσω της μεθόδου interrupt() ===== ===== Επανενεργοποίηση ενός νήματος μέσω της μεθόδου interrupt() =====
  
-Μία διακοπή (interrupt) αποτελεί ένδειξη προς την διεργασία να σταματήσει να κάνει αυτό που κάνει και να εκκινήσει κάτι διαφορετικό ή να τερματίσει. Εάν ένα νήμα έχει καλέσει την sleep().+Μία διακοπή (interrupt) αποτελεί ένδειξη προς την διεργασία να σταματήσει να κάνει αυτό που κάνει και να εκκινήσει κάτι διαφορετικό ή να τερματίσει. Η java υποστηρίζει την μέθοδο [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Thread.html#​interrupt()|Thread.interrupt()]] για την αποστολή ενός σήματος διακοπής σε ένα νήμα. Εάν ένα νήμα έχει καλέσει την sleep() ​η κλήση της interrupt() για το νήμα αυτό, θα το αφυπνίσει και θα παραχθεί ένα [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​InterruptedException.html|InterruptedException]] για το νήμα που κοιμόταν. Για τον λόγο αυτό, η κλήση της sleep() θα πρέπει να γίνεται πάντα μέσα σε ένα try/catch block της μορφής 
 + 
 +<code java> 
 +  try { 
 +    Thread.sleep(4000);​ 
 +  } catch (InterruptedException e) { 
 +    System.out.println(("​We'​ve been interrupted:​ no more messages."​);​ 
 +    return; 
 +  } 
 +</​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.1427203167.txt.gz · Last modified: 2016/02/26 11:15 (external edit)