thread resueltos hilos ejemplos detener control clase java concurrency locking condition countdownlatch

java - resueltos - Ponga un hilo a dormir hasta que se resuelva una condición en otro hilo



hilos en java pdf (3)

Cualquiera de los enfoques es más o menos equivalente, excepto que CountDownLatch solo se puede lanzar una vez. Después de eso, todas las llamadas await () regresan al instante. Entonces, un CyclicBarrier puede ser más apropiado si está trabajando con un servicio que puede ir hacia abajo y hacia arriba.

Si su condición es realmente un acuerdo de una sola vez, entonces FutureTask sería más apropiado. Puede llamar a get (), que esperaría a que el servicio esté disponible, y luego podría usar el servicio tan pronto como get () regrese.

Menciona que CountDownLatch permite esperar sin utilizar bloqueos. Sin embargo, CountDownLatch y ReentrantLock se implementan usando AbstractQueuedSynchronizer . Debajo del capó, proporcionan una semántica de sincronización y visibilidad idéntica.

Aquí hay dos trozos de código que logran (lo que pienso es) lo mismo.

Básicamente estoy tratando de aprender a usar la concurrencia de Java 1.5 para alejarme de Thread.sleep (long). El primer ejemplo usa ReentrantLock, y el segundo ejemplo usa CountDownLatch. La cuestión de lo que estoy tratando de hacer es poner un hilo a dormir hasta que se resuelva una condición en otro hilo.

ReentrantLock proporciona un bloqueo en el booleano que estoy usando para decidir si se activa el otro subproceso o no, y luego uso Condition with await / signal para poner en espera el otro subproceso. Por lo que puedo decir, la única razón por la que necesitaría utilizar bloqueos es si se necesita más de un hilo para escribir el acceso al booleano.

CountDownLatch parece proporcionar la misma funcionalidad que ReentrantLock pero sin los bloqueos (innecesarios?). Sin embargo, parece que estoy secuestrando su uso previsto al inicializarlo con solo una cuenta regresiva necesaria. Creo que se supone que debe usarse cuando varios hilos van a funcionar en la misma tarea, no cuando hay varios hilos esperando en una tarea.

Entonces, preguntas:

  1. ¿Estoy usando bloqueos para "lo correcto" en el código ReentrantLock? Si solo estoy escribiendo booleano en un hilo, ¿son necesarios los bloqueos? Mientras restablezca el booleano antes de despertar cualquier otro hilo, no puedo causar un problema, ¿o sí?

  2. ¿Existe una clase similar a CountDownLatch que pueda usar para evitar bloqueos (asumiendo que debería evitarlos en este caso) que es más apropiada para esta tarea?

  3. ¿Hay alguna otra forma de mejorar este código que debería tener en cuenta?

EJEMPLO UNO:

import java.util.concurrent.locks.*; public class ReentrantLockExample extends Thread { //boolean - Is the service down? boolean serviceDown; // I am using this lock to synchronize access to sDown Lock serviceLock; // and this condition to sleep any threads waiting on the service. Condition serviceCondition; public static void main(String[] args) { Lock l = new ReentrantLock(); Condition c = l.newCondition(); ReentrantLockExample rle = new ReentrantLockExample(l, c); //Imagine this thread figures out the service is down l.lock(); try { rle.serviceDown = true; } finally { l.unlock(); } int waitTime = (int) (Math.random() * 5000); System.out.println("From main: wait time is " + waitTime); rle.start(); try { //Symbolizes some random time that the service takes to come back up. Thread.sleep(waitTime); } catch (InterruptedException e) { e.printStackTrace(); } //Imagine this thread figures out that the service is back up. l.lock(); try { rle.serviceDown = false; c.signal(); } finally { l.unlock(); } } //Constructor public ReentrantLockExample(Lock l, Condition c) { this.serviceLock = l; this.serviceCondition = c; } /* * Should wait for this imaginary service to come back online. */ public void run() { System.out.println("Thread: start awaiting"); serviceLock.lock(); try { while (isServiceDown()) { serviceCondition.await(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { serviceLock.unlock(); } System.out.println("Thread: done awaiting"); } private boolean isServiceDown() { return serviceDown; } }

EJEMPLO DOS:

import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.*; public class CountDownLatchExample extends Thread { //boolean - Is the service down? boolean serviceDown; // I am using this latch to wait on the service. CountDownLatch serviceLatch; public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(1); CountDownLatchExample cdle = new CountDownLatchExample(cdl); //Service goes down. cdle.serviceDown = true; int waitTime = (int) (Math.random() * 5000); System.out.println("From main: wait time is " + waitTime); cdle.start(); try { //Symbolizes some random time that the service takes to come back up. Thread.sleep(waitTime); } catch (InterruptedException e) { e.printStackTrace(); } //Service comes back up. cdle.serviceDown = false; cdl.countDown(); } //Constructor public CountDownLatchExample(CountDownLatch cdl) { this.serviceLatch = cdl; } /* * Should wait for this imaginary service to come back online. */ public void run() { System.out.println("Thread: start awaiting"); try { while (isServiceDown()) { serviceLatch.await(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Thread: done awaiting"); } private boolean isServiceDown() { return serviceDown; } }


El enfoque de la variable de bloqueo / condición es mejor para esta tarea en mi opinión. Hay un ejemplo similar al suyo aquí: http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/Condition.html

En respuesta a la protección de un booleano. Puede usar volatile ( http://www.ibm.com/developerworks/java/library/j-jtp06197.html ). Sin embargo, el problema con el no uso de Locks es que, dependiendo de cuánto tiempo su servicio esté inactivo, continuará mientras (isServiceDown ()). Al usar una condición, espere que le diga al SO que duerma su hilo hasta que se despierte espurosamente (de lo que se habla en los documentos de Java para Condición), o hasta que la condición se señale en el otro hilo.