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:13] – [Υλοποίηση μίας διασυνδεδεμένης λίστας η οποία είναι συγχρονισμένη] 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 ===== | ||
- | ===== Παραδείγματα Χρήσης Εργαλείων Συγχρονισμού ===== | ||
- | ===== Blocking Queue με Locks ===== | + | ===== Atomic Integer, Long, Boolean, Reference |
- | Ας υποθέσουμε ότι έχετε | + | Στο πακέτο [[https:// |
- | + | ||
- | Για την επικοινωνία μεταξύ αναγνωστών και εγγραφέων θα χρησιμοποιηθεί ένα 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++) | + | * [[https://docs.oracle.com/ |
- | list.remove(0); | + | |
- | + | * [[https:// | |
- | if( list.isEmpty() ) | + | * [[https:// |
- | System.out.println( this.getName() +": list is empty!" | + | * [[https:// |
- | else | + | * [[https:// |
- | System.out.println( this.getName() +": list is NOT empty!" | + | * [[https:// |
- | | + | |
- | } | + | |
- | + | ||
- | class ListSynchronizer { | + | |
- | public static void main(String | + | |
- | SynchronizedList< | + | |
- | | + | |
- | + | ||
- | for(int i=0; i<10; i++) { | + | |
- | (new ListModifierThread(list)).start(); | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | </code> | + | |
- | + | ||
- | <WRAP tip 80% center round> | + | |
- | Αντί για τη συγχρονισμένη υλοποίηση της διασυνδεδεμένης λίστας που | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
+ | Οι βασικές μέθοδοι που διαθέτουν οι παραπάνω κλάσεις είναι οι εξής: | ||
+ | * **compareAndSet: | ||
+ | * **get:** Επιστρέφει την τρέχουσα τιμή. | ||
+ | * **getAndSet: | ||
+ | * **lazySet: | ||
+ | * **set:** Θέτει μία νέα τιμή για την μεταβλητή. | ||
java/java_util_concurrent.1490098427.txt.gz · Last modified: 2017/03/21 12:13 (external edit)