java:java_util_concurrent
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| java:java_util_concurrent [2017/03/21 12:29] – [Atomic Integer, Long, Boolean, Reference] gthanos | java:java_util_concurrent [2017/03/21 14:36] (current) – [Semaphore] gthanos | ||
|---|---|---|---|
| Line 37: | Line 37: | ||
| * **[[https:// | * **[[https:// | ||
| * **[[https:// | * **[[https:// | ||
| - | * **https:// | + | * **[[https:// |
| * **[[https:// | * **[[https:// | ||
| * **[[https:// | * **[[https:// | ||
| Line 61: | Line 61: | ||
| Υλοποίηση του παραπάνω // | Υλοποίηση του παραπάνω // | ||
| - | |||
| - | |||
| Line 74: | Line 72: | ||
| Το παραπάνω interface υλοποιείται μεσω της κλάσης [[http:// | Το παραπάνω interface υλοποιείται μεσω της κλάσης [[http:// | ||
| + | |||
| + | |||
| ===== Atomic Integer, Long, Boolean, Reference ===== | ===== Atomic Integer, Long, Boolean, Reference ===== | ||
| Στο πακέτο [[https:// | Στο πακέτο [[https:// | ||
| - | * [[AtomicBoolean: | + | * [[https:// |
| - | * [[AtomicInteger: | + | * [[https:// |
| - | * [[AtomicIntegerArray: | + | * [[https:// |
| - | * [[AtomicLong: | + | * [[https:// |
| - | * [[AtomicLongArray: | + | * [[https:// |
| - | * [[AtomicReference: | + | * [[https:// |
| - | * [[AtomicReferenceArray: | + | * [[https:// |
| Οι βασικές μέθοδοι που διαθέτουν οι παραπάνω κλάσεις είναι οι εξής: | Οι βασικές μέθοδοι που διαθέτουν οι παραπάνω κλάσεις είναι οι εξής: | ||
| Line 92: | Line 92: | ||
| * **lazySet: | * **lazySet: | ||
| * **set:** Θέτει μία νέα τιμή για την μεταβλητή. | * **set:** Θέτει μία νέα τιμή για την μεταβλητή. | ||
| - | |||
| - | |||
| - | ===== Παραδείγματα Χρήσης Εργαλείων Συγχρονισμού ===== | ||
| - | |||
| - | ===== Blocking Queue με Locks ===== | ||
| - | |||
| - | Ας υποθέσουμε ότι έχετε το αρχείο κειμένου {{: | ||
| - | |||
| - | Για την επικοινωνία μεταξύ αναγνωστών και εγγραφέων θα χρησιμοποιηθεί ένα blocking queue με σχετικά περιορισμένη χωρητικότητα **Κ**, όπου **K < min(M,N)**. Επίσης για την υλοποίηση του συγχρονισμού διαθέτουμε δύο κλειδαριές **α)** μία κλειδαριά η οποία βεβαιώνει ότι μόνο ένα νήμα διαβάζει από το αρχείο και γράφει στο //Blocking Queue// και **β)** μία κλειδαριά η οποία βεβαιώνει ότι μόνο ένα νήμα διαβάζει από το //Blocking Queue// και γράφει στο νέο αρχείο. | ||
| - | |||
| - | <WRAP tip 80% center round> | ||
| - | Για τον παρακάτω παράδειγμα κώδικα που υλοποιεί τον συγχρονισμό μεταξύ των νημάτων ανάγνωσης και εγγραφής, | ||
| - | </ | ||
| - | |||
| - | <code java BlockingQueueWithLocks.java> | ||
| - | import java.util.concurrent.*; | ||
| - | import java.util.concurrent.locks.*; | ||
| - | import java.io.*; | ||
| - | |||
| - | public class BlockingQueueWithLocks { | ||
| - | | ||
| - | public static void main(String args[]) { | ||
| - | BufferedReader in; | ||
| - | FileWriter out; | ||
| - | | ||
| - | if( args.length == 0 ) { | ||
| - | System.err.println(" | ||
| - | } | ||
| - | String filename = args[0]; | ||
| - | | ||
| - | try { | ||
| - | in = new BufferedReader(new FileReader(filename)); | ||
| - | out = new FileWriter(filename+" | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | ex.printStackTrace(); | ||
| - | return ; | ||
| - | } | ||
| - | | ||
| - | boolean useLocks = true; | ||
| - | | ||
| - | ArrayBlockingQueue< | ||
| - | ReentrantLock readLock = new ReentrantLock(); | ||
| - | ReentrantLock writeLock = new ReentrantLock(); | ||
| - | FileReaderQueueWriter w1 = new FileReaderQueueWriter(in, | ||
| - | FileReaderQueueWriter w2 = new FileReaderQueueWriter(in, | ||
| - | FileReaderQueueWriter w3 = new FileReaderQueueWriter(in, | ||
| - | FileWriterQueueReader r1 = new FileWriterQueueReader(out, | ||
| - | FileWriterQueueReader r2 = new FileWriterQueueReader(out, | ||
| - | FileWriterQueueReader r3 = new FileWriterQueueReader(out, | ||
| - | w1.start(); | ||
| - | w2.start(); | ||
| - | w3.start(); | ||
| - | r1.start(); | ||
| - | r2.start(); | ||
| - | r3.start(); | ||
| - | } | ||
| - | } | ||
| - | |||
| - | class FileReaderQueueWriter extends Thread { | ||
| - | BufferedReader in; | ||
| - | BlockingQueue< | ||
| - | ReentrantLock lock; | ||
| - | boolean useLocks; | ||
| - | | ||
| - | public FileReaderQueueWriter(BufferedReader in, BlockingQueue< | ||
| - | this.in = in; | ||
| - | this.queue = queue; | ||
| - | this.lock = lock; | ||
| - | setName(name); | ||
| - | this.useLocks = useLocks; | ||
| - | } | ||
| - | | ||
| - | void printError(String msg) { | ||
| - | System.err.println(" | ||
| - | } | ||
| - | | ||
| - | void printOut(String msg) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | | ||
| - | public void run() { | ||
| - | | ||
| - | int i=0; String input; | ||
| - | try { | ||
| - | while( true ) { | ||
| - | if( useLocks ) | ||
| - | lock.lock(); | ||
| - | input = in.readLine(); | ||
| - | if( input != null) { | ||
| - | queue.put(input); | ||
| - | | ||
| - | if( useLocks ) | ||
| - | lock.unlock(); | ||
| - | } | ||
| - | else { | ||
| - | if( useLocks ) | ||
| - | lock.unlock(); | ||
| - | break; | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | catch(IOException ex) { | ||
| - | printError(" | ||
| - | } | ||
| - | catch(InterruptedException ex) { | ||
| - | printError(" | ||
| - | } | ||
| - | finally { | ||
| - | if( useLocks && lock.isHeldByCurrentThread() ) | ||
| - | lock.unlock(); | ||
| - | try { | ||
| - | in.close(); | ||
| - | printError(" | ||
| - | } catch( IOException ex) { | ||
| - | printError(" | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | |||
| - | class FileWriterQueueReader extends Thread { | ||
| - | FileWriter writer; | ||
| - | BlockingQueue< | ||
| - | ReentrantLock lock; | ||
| - | boolean useLocks; | ||
| - | | ||
| - | public FileWriterQueueReader(FileWriter writer, BlockingQueue< | ||
| - | this.writer = writer; | ||
| - | this.queue = queue; | ||
| - | this.lock = lock; | ||
| - | setName(name); | ||
| - | this.useLocks = useLocks; | ||
| - | } | ||
| - | | ||
| - | void printError(String msg) { | ||
| - | System.err.println(" | ||
| - | } | ||
| - | | ||
| - | void printOut(String msg) { | ||
| - | System.out.println(" | ||
| - | } | ||
| - | | ||
| - | public void run() { | ||
| - | try { | ||
| - | String input; | ||
| - | while( true) { | ||
| - | if( useLocks ) | ||
| - | lock.lock(); | ||
| - | if( (input = queue.poll(500, | ||
| - | input += " | ||
| - | writer.append( input.subSequence(0, | ||
| - | if( useLocks ) | ||
| - | lock.unlock(); | ||
| - | } | ||
| - | else { | ||
| - | if( useLocks ) | ||
| - | lock.unlock(); | ||
| - | break; | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | } catch(IOException ex) { | ||
| - | | ||
| - | } catch(InterruptedException ex) { | ||
| - | | ||
| - | } finally { | ||
| - | if( useLocks && lock.isHeldByCurrentThread() ) | ||
| - | lock.unlock(); | ||
| - | try { | ||
| - | writer.close(); | ||
| - | printError(" | ||
| - | } catch( IOException ex) { | ||
| - | printError(" | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ==== Υλοποίηση μίας διασυνδεδεμένης λίστας η οποία είναι συγχρονισμένη ==== | ||
| - | |||
| - | Όπως ίσως θα γνωρίζετε η διασυνδεδεμένες λίστες που υπάρχουν στο πακέτο **[[https:// | ||
| - | |||
| - | Δείτε πως διαμορφώνεται η κλάση καθώς και ένα παράδειγμα χρήσης της κλάσης αυτής. | ||
| - | |||
| - | <code java SynchronizedList.java> | ||
| - | import java.util.*; | ||
| - | import java.util.concurrent.*; | ||
| - | import java.util.concurrent.locks.*; | ||
| - | |||
| - | class SynchronizedList< | ||
| - | | ||
| - | ArrayList< | ||
| - | ReentrantReadWriteLock lock; | ||
| - | Lock rlock, wlock; | ||
| - | | ||
| - | public SynchronizedList() { | ||
| - | list = new ArrayList<> | ||
| - | lock = new ReentrantReadWriteLock(); | ||
| - | rlock = lock.readLock(); | ||
| - | wlock = lock.writeLock(); | ||
| - | } | ||
| - | | ||
| - | public SynchronizedList(int capacity) { | ||
| - | list = new ArrayList<> | ||
| - | lock = new ReentrantReadWriteLock(); | ||
| - | rlock = lock.readLock(); | ||
| - | wlock = lock.writeLock(); | ||
| - | } | ||
| - | | ||
| - | public void listWriteLock() { | ||
| - | wlock.lock(); | ||
| - | } | ||
| - | | ||
| - | public void listWriteUnlock() { | ||
| - | wlock.unlock(); | ||
| - | } | ||
| - | | ||
| - | public void listReadLock() { | ||
| - | rlock.lock(); | ||
| - | } | ||
| - | | ||
| - | public void listReadUnlock() { | ||
| - | rlock.unlock(); | ||
| - | } | ||
| - | | ||
| - | public void add(E e) { | ||
| - | wlock.lock(); | ||
| - | list.add(e); | ||
| - | wlock.unlock(); | ||
| - | } | ||
| - | | ||
| - | public void add(int index, E e) { | ||
| - | wlock.lock(); | ||
| - | list.add(index, | ||
| - | wlock.unlock(); | ||
| - | } | ||
| - | | ||
| - | public boolean addAll(Collection<? | ||
| - | wlock.lock(); | ||
| - | boolean result = list.addAll(c); | ||
| - | wlock.unlock(); | ||
| - | return result; | ||
| - | } | ||
| - | | ||
| - | public void clear() { | ||
| - | wlock.lock(); | ||
| - | list.clear(); | ||
| - | wlock.unlock(); | ||
| - | } | ||
| - | | ||
| - | public boolean contains(Object o) { | ||
| - | rlock.lock(); | ||
| - | boolean result = list.contains(o); | ||
| - | rlock.unlock(); | ||
| - | return result; | ||
| - | } | ||
| - | | ||
| - | public void ensureCapacity(int minCapacity) { | ||
| - | wlock.lock(); | ||
| - | list.ensureCapacity(minCapacity); | ||
| - | wlock.unlock(); | ||
| - | } | ||
| - | | ||
| - | public E get(int index) { | ||
| - | rlock.lock(); | ||
| - | E e = list.get(index); | ||
| - | rlock.unlock(); | ||
| - | return e; | ||
| - | } | ||
| - | | ||
| - | public int indexOf(Object o) { | ||
| - | rlock.lock(); | ||
| - | int index = list.indexOf(o); | ||
| - | rlock.unlock(); | ||
| - | return index; | ||
| - | } | ||
| - | | ||
| - | public boolean isEmpty() { | ||
| - | rlock.lock(); | ||
| - | boolean empty = list.isEmpty(); | ||
| - | rlock.unlock(); | ||
| - | return empty; | ||
| - | } | ||
| - | | ||
| - | public int lastIndexOf(Object o) { | ||
| - | rlock.lock(); | ||
| - | int lastIndex = list.lastIndexOf(o); | ||
| - | rlock.unlock(); | ||
| - | return lastIndex; | ||
| - | } | ||
| - | | ||
| - | public E remove(int index) { | ||
| - | wlock.lock(); | ||
| - | E e = list.remove(index); | ||
| - | wlock.unlock(); | ||
| - | return e; | ||
| - | } | ||
| - | | ||
| - | public E set(int index, E element) { | ||
| - | wlock.lock(); | ||
| - | E e = list.set(index, | ||
| - | wlock.unlock(); | ||
| - | return e; | ||
| - | } | ||
| - | | ||
| - | public int size() { | ||
| - | rlock.lock(); | ||
| - | int lsize = list.size(); | ||
| - | rlock.unlock(); | ||
| - | return lsize; | ||
| - | } | ||
| - | | ||
| - | List< | ||
| - | rlock.lock(); | ||
| - | List< | ||
| - | rlock.unlock(); | ||
| - | return newlist; | ||
| - | } | ||
| - | | ||
| - | class SyncrhonizedIterator implements Iterator< | ||
| - | Iterator it; | ||
| - | Lock rlock; | ||
| - | Lock wlock; | ||
| - | | ||
| - | public SyncrhonizedIterator(Lock readlock, Lock writelock) { | ||
| - | rlock = readlock; | ||
| - | wlock = writelock; | ||
| - | it = list.iterator(); | ||
| - | } | ||
| - | | ||
| - | public boolean hasNext() { | ||
| - | rlock.lock(); | ||
| - | boolean hasnext = it.hasNext(); | ||
| - | rlock.unlock(); | ||
| - | return hasnext; | ||
| - | } | ||
| - | | ||
| - | public E next() { | ||
| - | rlock.lock(); | ||
| - | Object o = it.next(); | ||
| - | rlock.unlock(); | ||
| - | return (E)o; | ||
| - | } | ||
| - | | ||
| - | public void remove() { | ||
| - | wlock.lock(); | ||
| - | it.remove(); | ||
| - | wlock.unlock(); | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | |||
| - | class ListModifierThread extends Thread { | ||
| - | Random rand; | ||
| - | SynchronizedList< | ||
| - | // | ||
| - | | ||
| - | public ListModifierThread(SynchronizedList< | ||
| - | //public ListModifierThread(ArrayList< | ||
| - | this.list = list; | ||
| - | rand = new Random( new Date().getTime() ); | ||
| - | } | ||
| - | | ||
| - | public void run() { | ||
| - | for(int i=0; i<1000; i++) | ||
| - | list.add( rand.nextInt(1000) ); | ||
| - | |||
| - | for(int i=0; i<1000; i++) | ||
| - | list.remove(0); | ||
| - | | ||
| - | if( list.isEmpty() ) | ||
| - | System.out.println( this.getName() +": list is empty!" | ||
| - | else | ||
| - | System.out.println( this.getName() +": list is NOT empty!" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | class ListSynchronizer { | ||
| - | public static void main(String []args) { | ||
| - | SynchronizedList< | ||
| - | // | ||
| - | | ||
| - | for(int i=0; i<10; i++) { | ||
| - | (new ListModifierThread(list)).start(); | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | <WRAP tip 80% center round> | ||
| - | Αντί για τη συγχρονισμένη υλοποίηση της διασυνδεδεμένης λίστας που χρησιμοποιήσαμε μπορείτε να χρησιμοποιήσετε ένα απλό java.util.ArrayList. Αλλάξτε τον κώδικα και δείτε την συμπεριφορά (το πρόγραμμα εμφανίζει // | ||
| - | </ | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
java/java_util_concurrent.1490099344.txt.gz · Last modified: 2017/03/21 12:29 by gthanos
