User Tools

Site Tools


java:concurrency_intro

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
java:concurrency_intro [2017/03/19 16:59] – [Περιμένοντας ένα νήμα να ολοκληρώσει μέσω της μεθόδου join()] gthanosjava:concurrency_intro [2018/03/08 10:37] (current) – [Εφαρμόζοντας τις μεθόδους sleep()/interrupt()/join() σε ένα παράδειγμα] gthanos
Line 9: Line 9:
 ===== Νήματα (Threads) ===== ===== Νήματα (Threads) =====
  
-Τα νήματα αναφέρονται συχνά και ως lightweight processes. Τόσο οι διεργασίες όσο και τα νήματα παρέχουν ένα περιβάλλον εκτέλεσης, αλλά απαιτούν λιγότερους πόρους κατά την δημιουργία τους σε σχέση με μία διεργασία. Τα νήματα ζουν μέσα στις διεργασίες (κάθε διεργασία έχει τουλάχιστον ένα νήμα) και μοιράζονται τους πόρους της διεργασίας, δηλαδή την μνήμη και τα αρχεία που έχει ανοίξει η διεργασία.+Τα νήματα αναφέρονται συχνά και ως lightweight processes. Σε αναλογία με τις διεργασίες τα νήματα παρέχουν ένα περιβάλλον εκτέλεσης, αλλά απαιτούν λιγότερους πόρους κατά την δημιουργία τους σε σχέση με μία διεργασία. Τα νήματα ζουν μέσα στις διεργασίες (κάθε διεργασία έχει τουλάχιστον ένα νήμα) και μοιράζονται τους πόρους της διεργασίας, δηλαδή την μνήμη και τα αρχεία που έχει ανοίξει η διεργασία.
  
 Η πολυνηματική εκτέλεση αποτελεί ένα από τα βασικά χαρακτηριστικά της πλατφόρμας Java. Κάθε Java εφαρμογή έχει  ένα αρχικό νήμα εκτέλεσης, το οποίο εκκινεί μέσω της μεθόδου //main//. Το νήμα αυτό έχει τη δυνατότητα να δημιουργήσει πρόσθετα νήματα, μέσω της διαδικασίας που περιγράφεται παρακάτω. Η πολυνηματική εκτέλεση αποτελεί ένα από τα βασικά χαρακτηριστικά της πλατφόρμας Java. Κάθε Java εφαρμογή έχει  ένα αρχικό νήμα εκτέλεσης, το οποίο εκκινεί μέσω της μεθόδου //main//. Το νήμα αυτό έχει τη δυνατότητα να δημιουργήσει πρόσθετα νήματα, μέσω της διαδικασίας που περιγράφεται παρακάτω.
Line 19: Line 19:
 <code java HelloRunnable.java> <code java HelloRunnable.java>
 public class HelloRunnable implements Runnable { public class HelloRunnable implements Runnable {
 +  public void run() {
 +    System.out.println("Hello from a thread!");
 +  }
  
-    public void run() { +  public static void main(String args[]) { 
-        System.out.println("Hello from a thread!"); +    (new Thread(new HelloRunnable())).start(); 
-    } +  }
- +
-    public static void main(String args[]) { +
-        (new Thread(new HelloRunnable())).start(); +
-    }+
 } }
 </code> </code>
Line 32: Line 31:
 <code java HelloThread.java> <code java HelloThread.java>
 public class HelloThread extends Thread { public class HelloThread extends Thread {
 +  public void run() {
 +    System.out.println("Hello from a thread!");
 +  }
  
-    public void run() { +  public static void main(String args[]) { 
-        System.out.println("Hello from a thread!"); +    (new HelloThread()).start(); 
-    } +  }
- +
-    public static void main(String args[]) { +
-        (new HelloThread()).start(); +
-    }+
 } }
 </code> </code>
  
-Παρατηρείστε ότι και τα δύο παραπάνω παραδείγματα καλούν την μέθοδο [[http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#start()|Thread.start()]]. Από τα δύο παραπάνω τρόπους ο πρώτος έχει το πλεονέκτημα ότι η νηματική κλάση δεν κληρονομεί κάποια άλλη κλάση. Στην περίπτωση που η νηματική κλάση θέλουμε να κληρονομήσει κάποια κλάση εκτός της [[http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html|Thread]], μπορούμε να χρησιμοποιήσουμε μόνο τον πρώτο τρόπο.+Παρατηρείστε ότι και τα δύο παραπάνω παραδείγματα καλούν την μέθοδο [[http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#start()|Thread.start()]]. Από τα δύο παραπάνω τρόπους ο πρώτος έχει το πλεονέκτημα ότι η νηματική κλάση δεν κληρονομεί την κλάση [[http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html|Thread]] (επομένως μπορεί να κληρονομήσει μία άλλη κλάση) και το μειονέκτημα ότι η νηματική κλάση δεν μπορεί να χρησιμοποιήσει καμία από τις μεθόδους που υλοποιεί η κλάση [[http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html|Thread]] α τις δούμε παρακάτω).
  
-===== Σταματώντας την εκτέλεση ενός νήματος μέσω της μεθόδου sleep() =====+===== Αναβάλλοντας την εκτέλεση ενός νήματος μέσω της μεθόδου sleep() =====
  
-Η μέθοδος [[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#sleep-long-|sleep]] δίνει την δυνατότητα σε ένα νήμα να σταματήσει την εκτέλεση του για ένα συγκεκριμένο χρονικό διάστημα. Κατά το διάστημα αυτό, άλλα νήματα της τρέχουσας διεργασίας μπορούν να εκτελεστούν. Θα πρέπει να έχουμε υπόψη μας ότι η χρονική διάρκεια κατά την οποία θα παύσει η εκτέλεση του νήματος μπορεί να έχει μικρές αποκλίσεις από τη χρονική διάρκεια που προσδιορίζεται στα ορίσματα της μεθόδου. Δείτε το παρακάτω παράδειγμα χρήσης της μεθόδου [http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#sleep-long-|sleep]].+Η μέθοδος [[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#sleep-long-|sleep]] δίνει την δυνατότητα σε ένα νήμα να σταματήσει την εκτέλεση του για ένα συγκεκριμένο χρονικό διάστημα. Κατά το διάστημα αυτό, άλλα νήματα της τρέχουσας διεργασίας μπορούν να εκτελεστούν. Θα πρέπει να έχουμε υπόψη μας ότι η χρονική διάρκεια κατά την οποία θα παύσει η εκτέλεση του νήματος μπορεί να έχει μικρές αποκλίσεις από τη χρονική διάρκεια που προσδιορίζεται στα ορίσματα της μεθόδου. Δείτε το παρακάτω παράδειγμα χρήσης της μεθόδου [[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#sleep-long-|sleep]].
  
 <code java SleepMessages.java> <code java SleepMessages.java>
 public class SleepMessages { public class SleepMessages {
-    public static void main(String args[]) +  public static void main(String args[]) 
-        throws InterruptedException { +    throws InterruptedException { 
-        String importantInfo[] = { +    String importantInfo[] = { 
-            "Mares eat oats", +      "Peter Pan",  
-            "Does eat oats", +      "leader of the Lost Boys",  
-            "Little lambs eat ivy", +      "goes to Neverland
-            "A kid will eat ivy too+    };
-        };+
  
-        for (int i=0; i<importantInfo.length; i++) { +    for (int i=0; i<importantInfo.length; i++) { 
-            //Pause for 2 seconds +      //Pause for 2 seconds 
-            Thread.sleep(2000); +      Thread.sleep(2000); 
-            //Print a message +      //Print a message 
-            System.out.println(importantInfo[i]); +      System.out.println(importantInfo[i]);
-        }+
     }     }
 +  }
 } }
 </code> </code>
Line 74: Line 71:
 </WRAP> </WRAP>
  
-===== Επανενεργοποίηση ενός νήματος μέσω της μεθόδου interrupt() =====+===== Αφύπνιση ενός νήματος μέσω της μεθόδου interrupt() =====
  
 Μία διακοπή (//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|java.lang.InterruptedException]] για το νήμα που κοιμόταν. Για τον λόγο αυτό, η κλήση της //sleep// θα πρέπει να γίνεται πάντα μέσα σε ένα //try/catch block// της μορφής Μία διακοπή (//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|java.lang.InterruptedException]] για το νήμα που κοιμόταν. Για τον λόγο αυτό, η κλήση της //sleep// θα πρέπει να γίνεται πάντα μέσα σε ένα //try/catch block// της μορφής
Line 82: Line 79:
     Thread.sleep(4000);     Thread.sleep(4000);
   } catch (InterruptedException e) {   } catch (InterruptedException e) {
-    System.out.println(("We've been interrupted: no more messages.");+    System.out.println("We've been interrupted: no more messages.");
     return;     return;
   }   }
Line 121: Line 118:
 ===== Εφαρμόζοντας τις μεθόδους sleep()/interrupt()/join() σε ένα παράδειγμα ===== ===== Εφαρμόζοντας τις μεθόδους sleep()/interrupt()/join() σε ένα παράδειγμα =====
  
-Δείτε το παρακάτω παράδειγμα εκτέλεσης δύο νημάτων, το οποίο χρησιμοποιεί τις μεθόδους sleep(), interrupt() και join(). Το κεντρικό νήμα (μέθοδος main) περιμένει το νήμα που δημιουργείται για δεδομένο χρονικό διάστημα. Κάθε 1 δευτερόλεπτο το κεντρικό νήμα επιστρέφει από την μέθοδο **join(1000)** και εξετάζει εάν a)ο χρόνος εκτέλεσης του ολοκληρώθηκε και b) το παιδί τελείωσε μέσω της **t.isAlive()**. Εάν ισχύουν και οι δύο παραπάνω προϋποθέσεις τότε στέλνει ένα interrupt στο παιδί και περιμένει έως ότου αυτό να τερματίσει μέσω της **t.join()**. Στην συνέχεια ολοκληρώνει και το κεντρικό νήμα την εκτέλεση του.+Δείτε το παρακάτω παράδειγμα εκτέλεσης δύο νημάτων, το οποίο χρησιμοποιεί τις μεθόδους [[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#sleep-long-|sleep]][[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupt--|interrupt]] και [[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join--|join]]. Το κεντρικό νήμα (μέθοδος main) περιμένει το νήμα που δημιουργείται για δεδομένο χρονικό διάστημα. Κάθε 1 δευτερόλεπτο το κεντρικό νήμα επιστρέφει από την μέθοδο **join(1000)** και εξετάζει εάν  
 +  - ο χρόνος εκτέλεσης του ολοκληρώθηκε και  
 +  - το παιδί δεν έχει ολοκληρώσει την εκτέλεση του. Ο έλεγχος γίνεται μέσω της μεθόδου [[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#isAlive--|isAlive]] 
 +  
 +Εάν ισχύουν και οι δύο παραπάνω προϋποθέσεις τότε στέλνει ένα //interrupt// στο παιδί και περιμένει έως ότου αυτό να τερματίσει μέσω της **t.join()**. Στην συνέχεια ολοκληρώνει και το κεντρικό νήμα την εκτέλεση του.
  
 <code java MessageLoops.java> <code java MessageLoops.java>
Line 208: Line 209:
 }</code> }</code>
  
- +|Προηγούμενο: [[:java:sockets | Sockets ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:synchronization| Προβλήματα συγχρονισμού με χρήση νημάτων ]]|
- +
- +
- +
java/concurrency_intro.1489942770.txt.gz · Last modified: 2017/03/19 16:59 by gthanos