| Both sides previous revision
Previous revision
Next revision
|
Previous revision
Next revision
Both sides next revision
|
java:java_util_concurrent [2017/03/21 11:43] gthanos [Blocking Queue με Locks] |
java:java_util_concurrent [2017/03/21 12:29] gthanos [Atomic Integer, Long, Boolean, Reference] |
| Το παραπάνω interface υλοποιείται μεσω της κλάσης [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html||java.util.concurrent.locks.ReentrantReadWriteLock]]. Η κλάση αυτή περιέχει δύο άλλες εσωτερικές κλάσεις την [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.ReadLock.html|ReentrantReadWriteLock.ReadLock]] και [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.WriteLock.html|ReentrantReadWriteLock.WriteLock]]. Η πρώτη χρησιμοποιείται για διάβασμα και η δεύτερη για γράψιμο. | Το παραπάνω interface υλοποιείται μεσω της κλάσης [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html||java.util.concurrent.locks.ReentrantReadWriteLock]]. Η κλάση αυτή περιέχει δύο άλλες εσωτερικές κλάσεις την [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.ReadLock.html|ReentrantReadWriteLock.ReadLock]] και [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.WriteLock.html|ReentrantReadWriteLock.WriteLock]]. Η πρώτη χρησιμοποιείται για διάβασμα και η δεύτερη για γράψιμο. |
| ===== Atomic Integer, Long, Boolean, Reference ===== | ===== Atomic Integer, Long, Boolean, Reference ===== |
| | |
| | Στο πακέτο [[https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html|java.util.concurrent.atomic]] η γλώσσα παρέχει ισοδύναμους των βασικών τύπων δεδομένων οι οποίοι όμως μπορούν να προσπελαστούν από δύο ή περισσότερα νήματα χωρίς να προκύψει ασάφεια ως προς την τιμή τους. Οι τύποι αυτοί είναι οι εξής: |
| | |
| | * [[AtomicBoolean:]] Μία boolean μεταβλητή η οποία μπορεί να αλλάξει τιμή ατομικά. |
| | * [[AtomicInteger:]] Μία Integer μεταβλητή η οποία μπορεί να αλλάξει τιμή ατομικά. |
| | * [[AtomicIntegerArray:]] Ένας πίνακας από ακεραίους του οποίου τα στοιχεία μπορούν να αλλάξουν τιμή ατομικά. |
| | * [[AtomicLong:]] Μία Long μεταβλητή η οποία μπορεί να αλλάξει τιμή ατομικά. |
| | * [[AtomicLongArray:]] Ένας πίνακας από ακεραίους τύπου Long του οποίου τα στοιχεία μπορούν να αλλάξουν τιμή ατομικά. |
| | * [[AtomicReference:]] Μία αναφορά σε αντικείμενο η οποία μπορεί να αλλάξει ατομικά. |
| | * [[AtomicReferenceArray:]] Ένας πίνακας από αναφορές του οποίου τα στοιχεία μπορούν να αλλάξουν τιμή ατομικά. |
| | |
| | Οι βασικές μέθοδοι που διαθέτουν οι παραπάνω κλάσεις είναι οι εξής: |
| | * **compareAndSet:** Η μέθοδος αλλάζει την τιμή της μεταβλητής με την προϋπόθεση ότι η υφιστάμενη τιμή ταυτίζεται με το 1ο όρισμα της μεθόδου. |
| | * **get:** Επιστρέφει την τρέχουσα τιμή. |
| | * **getAndSet:** Επιστρέφει την υφιστάμενη τιμή και την ανανεώνει με μία νέα. |
| | * **lazySet:** Θέτει μία νέα τιμή για την μεταβλητή. |
| | * **set:** Θέτει μία νέα τιμή για την μεταβλητή. |
| | |
| |
| ===== Παραδείγματα Χρήσης Εργαλείων Συγχρονισμού ===== | ===== Παραδείγματα Χρήσης Εργαλείων Συγχρονισμού ===== |
| </WRAP> | </WRAP> |
| |
| <code java UtilConcurrentDemo1.java> | <code java BlockingQueueWithLocks.java> |
| import java.util.concurrent.*; | import java.util.concurrent.*; |
| import java.util.concurrent.locks.*; | import java.util.concurrent.locks.*; |
| ==== Υλοποίηση μίας διασυνδεδεμένης λίστας η οποία είναι συγχρονισμένη ==== | ==== Υλοποίηση μίας διασυνδεδεμένης λίστας η οποία είναι συγχρονισμένη ==== |
| |
| Όπως ίσως θα γνωρίζετε η διασυνδεδεμένες λίστες που υπάρχουν στο πακέτο java.util δεν είναι συγχρονισμένες, δηλαδή δεν μπορούν να προσπελαστούν ταυτόχρονα από δύο ή περισσότερα νήματα. Προκειμένου να μπορούμε να προσπελάσουμε μία λίστα από περισσότερα του ενός νήματα δημιουργούμε την κλάση SynchronizedList η οποία χρησιμοποιεί ένα [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.ReadLock.html|java.util.concurrent.locks.ReentrantLock.ReadLock]] για διάβασμα και ένα [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.ReadLock.html|ReentrantReadWriteLock.WriteLock.html]] για μεταβολή του περιεχομένου της λίστας. | Όπως ίσως θα γνωρίζετε η διασυνδεδεμένες λίστες που υπάρχουν στο πακέτο **[[https://docs.oracle.com/javase/7/docs/api/java/util/package-frame.html|java.util]]** δεν είναι συγχρονισμένες, δηλαδή δεν μπορούν να παρέχουν καμία εγγύηση ότι εάν προσπελαστούν ταυτόχρονα από δύο ή περισσότερα νήματα η δομή θα διατηρήσει την εσωτερική της συνοχή και το περιεχόμενο της θα είναι σωστό. Προκειμένου να μπορούμε να προσπελάσουμε μία λίστα από περισσότερα του ενός νήματα δημιουργούμε την κλάση SynchronizedList η οποία χρησιμοποιεί ένα [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.ReadLock.html|java.util.concurrent.locks.ReentrantLock.ReadLock]] για διάβασμα και ένα [[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.ReadLock.html|ReentrantReadWriteLock.WriteLock.html]] για μεταβολή του περιεχομένου της λίστας. |
| |
| Δείτε πως διαμορφώνεται η κλάση καθώς και ένα παράδειγμα χρήσης της κλάσης αυτής. | Δείτε πως διαμορφώνεται η κλάση καθώς και ένα παράδειγμα χρήσης της κλάσης αυτής. |
| |
| <code java UtilConcurrentDemo2.java> | <code java SynchronizedList.java> |
| import java.util.*; | import java.util.*; |
| import java.util.concurrent.*; | import java.util.concurrent.*; |
| Random rand; | Random rand; |
| SynchronizedList<Integer> list; | SynchronizedList<Integer> list; |
| | //ArrayList<Integer> list; |
| | |
| public ListModifierThread(SynchronizedList<Integer> list) { | public ListModifierThread(SynchronizedList<Integer> list) { |
| | //public ListModifierThread(ArrayList<Integer> list) { |
| this.list = list; | this.list = list; |
| rand = new Random( new Date().getTime() ); | rand = new Random( new Date().getTime() ); |
| list.add( rand.nextInt(1000) ); | list.add( rand.nextInt(1000) ); |
| | |
| list.listWriteLock(); | for(int i=0; i<1000; i++) |
| while( list.size() > 0 ) | list.remove(0); |
| System.out.println( list.remove( list.size()-1 ) ); | |
| | |
| if( list.isEmpty() ) | if( list.isEmpty() ) |
| else | else |
| System.out.println( this.getName() +": list is NOT empty!"); | System.out.println( this.getName() +": list is NOT empty!"); |
| list.listWriteUnlock(); | |
| } | } |
| } | } |
| public static void main(String []args) { | public static void main(String []args) { |
| SynchronizedList<Integer> list = new SynchronizedList<>(); | SynchronizedList<Integer> list = new SynchronizedList<>(); |
| | //ArrayList<Integer> list = new ArrayList<>(); |
| | |
| for(int i=0; i<10; i++) { | for(int i=0; i<10; i++) { |