| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
Keskustelut - Java - notify() vs. notifyAll() + InterruptedException wait():stacoderodde 17:44 16.8.12 Terve! (Rinnakkais-)ohjelmointikysymys, joten on lähdettävä jostain liikkeelle; "tässä koodi!": Java public class SemaphoreMonitor { private volatile int permits; public SemaphoreMonitor(int permits){ if (permits < 1) { throw new IllegalArgumentException("Invalid semaphore requested."); } this.permits = permits; } public synchronized void acquire() { while (permits == 0) { try { wait(); } catch (InterruptedException e) {} } permits--; } public synchronized void release() { permits++; notify(); } static class FunkyDigits { private int[] digits; private SemaphoreMonitor mutex; private long minDelay = Long.MAX_VALUE; private long maxDelay = Long.MIN_VALUE; FunkyDigits(){ mutex = new SemaphoreMonitor(1); digits = new int[20]; for (int i = 0; i < digits.length; i++) { digits[i] = i + 1; } } public String toString(){ StringBuilder sb = new StringBuilder(1000); for(int i : digits) { sb.append(i); sb.append(' '); } return sb.toString(); } void reverse(){ long ta = System.nanoTime(); mutex.acquire(); long tb = System.nanoTime(); if (minDelay > tb - ta) { minDelay = tb - ta; } if (maxDelay < tb - ta) { maxDelay = tb - ta; } for (int i = 0, j = digits.length - 1; i < j; i++, j--) { int tmp = digits[i]; digits[i] = digits[j]; digits[j] = tmp; } mutex.release(); } long getMinDelay() { return minDelay; } long getMaxDelay() { return maxDelay; } } static class FunkyThread extends Thread { private FunkyDigits digits; long invocations; FunkyThread(FunkyDigits digits) { this.digits = digits; } public void run() { long ta = System.currentTimeMillis(); while (System.currentTimeMillis() - ta < 1000L) { digits.reverse(); invocations++; } } } public static void main(String[] args) { FunkyDigits digits = new FunkyDigits(); FunkyThread ft1 = new FunkyThread(digits); FunkyThread ft2 = new FunkyThread(digits); FunkyThread ft3 = new FunkyThread(digits); FunkyThread ft4 = new FunkyThread(digits); ft1.start(); ft2.start(); ft3.start(); ft4.start(); try { ft1.join(); } catch (InterruptedException e) { e.printStackTrace(); } try { ft2.join(); } catch (InterruptedException e) { e.printStackTrace(); } try { ft3.join(); } catch (InterruptedException e) { e.printStackTrace(); } try { ft4.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(digits); System.out.println("Invocations by ft1: " + ft1.invocations); System.out.println("Invocations by ft2: " + ft2.invocations); System.out.println("Invocations by ft3: " + ft3.invocations); System.out.println("Invocations by ft4: " + ft4.invocations); System.out.println("Maximum delay: " + digits.getMaxDelay() + " ns."); } } Outermost luokka (SemaphoreMonitor) yrittää mallintaa semafooria. Lisäksi meillä on käytössä luokka (FunkyDigits), joka pitää sisällään 20 int-arvoa. (FD:n konstruktori asettaa taulukon arvoihin 1, 2, ..., 20.) Koodista löytyy myöskin FD:n operaatiota reverse() toistuvasti suorittava säieluokka FunkyThread. FD:n reverse() metodi käyttää ym. SemaphoreMonitor:ia synkronointiin. Toistaiseksi ohjelmaa näyttää toimivan: ilman synkronointia ohjelma tulostaa hassunnäköisen palindromin, ja SM:ää käytettäessä tulee laskeva/nouseva alkuperäis-inttien jono sen mukaan, onko reverse():a kutsuttu pariton/parillinen määrä. Nyt asiaan: (1) onko acquire()-metodissa InterruptedException hoidettu oikein vai rinnakkaisuusartifaktit ovat silti mahdollisia? (2) release()-metodissa kokeilin sekä notify():n, että notifyAll():n; juuri tähän ohjelmaan ei päällepäin näyttäisi olevan vaikutusta kumpaa käytän. Osaisitko antaa esimerkin tilanteesta, jossa väärästä notify*():sta saattaisi tulla ongelmia? |
![]() Haku
|