2012-09-25 26 views
5

Soy nuevo en multi-threading y mientras leo sobre multi-threading, pensé en escribir este código de multi-threading para hacer lo siguiente.Cómo esperar desde thread1 hasta que se lo notifique por thread2

Mi clase de contador es la siguiente.

class Counter { 
    private int c = 0; 

    public void increment() { 
    System.out.println("increment value: "+c); 
     c++; 
    } 

    public void decrement() { 
     c--; 
     System.out.println("decrement value: "+c); 
    } 

    public int value() { 
     return c; 
    } 

} 

Este objeto de contador se comparte entre dos hilos. Una vez que se inician los hilos, necesito hacer lo siguiente. Quiero que Thread2 espere hasta que Thread1 incremente el conteo del objeto Counter en 1. Una vez hecho esto, Then Thread 1 informa thread2 y luego Thread1 comienza a esperar que thread2 disminuya el valor en 1. Entonces thread2 inicia y disminuye el valor por 1 e informa thread1 nuevamente y luego thread2 comienza a esperar thread1. Repita este proceso por algunas veces.

¿Cómo puedo lograr esto. Muchas gracias de antemano.

He hecho lo siguiente.

public class ConcurrencyExample { 

    private static Counter counter; 
    private static DecrementCount t1; 
    private static IncrementCount t2; 

    public static void main(String[] args) { 
    Counter counter = new Counter(); 
    Thread t1 = new Thread(new IncrementCount(counter)); 
    t1.start(); 

    Thread t2 = new Thread(new DecrementCount(counter)); 
    t2.start(); 

    } 

} 


public class DecrementCount implements Runnable { 

    private static Counter counter; 

    public DecrementCount(Counter counter) { 
    this.counter = counter; 
    } 

    @Override 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
     counter.decrement();  
     System.out.println("decreamented"); 
    } 
    } 

} 


public class IncrementCount implements Runnable { 

    private static Counter counter; 

    public IncrementCount(Counter counter) { 
    this.counter = counter; 
    } 

    @Override 
    public void run() { 
    for (int i = 0; i < 1000; i++) { 
     counter.increment(); 
     System.out.println("Incremented"); 
    } 

    } 

} 
+2

Consulte CountDownLatch: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html – davidmontoyago

+1

'IncrementCount' debe llamar a 'increment()', ¿no? –

+1

La forma más sencilla de hacer esto sería usar un hilo. Sugiero que considere ejemplos en los que el uso de varios hilos sea más rápido, en lugar de más complicado y más lento. –

Respuesta

3

Echa un vistazo Semaphore. Necesitará dos, uno para cada hilo: incSemaphore y decSemaphore. En DecrementCount hacer:

for (int i = 0; i < 1000; i++) { 
    decSemaphore.acquire(); 
    counter.decrement();  
    System.out.println("decreamented"); 
    incSemaphore.release(); 
} 

Implementar IncrementCount simétricamente. El valor inicial de incSemaphore debe ser 1 y 0 para decSemaphore.

BTW su Counter también requiere sincronización (consulte la palabra clave synchronized y AtomicInteger).

+0

+1 para mayor claridad. – dcernahoschi

0

Use Condition con boolean flag.

final Lock lock = new ReentrantLock(); 
final Condition incremented= lock.newCondition(); 
final Condition decremented= lock.newCondition(); 

Cambiar su contador a continuación

Explicación:

Hemos utilizado dos condiciones se incrementa uno y uno es disminuido. basado en la bandera booleana, verificamos si tenemos que esperar con una condición o no.

class Counter { 
private int c = 0; 
boolean increment = false; 

final Lock lock = new ReentrantLock(); 
final Condition incremented = lock.newCondition(); 
final Condition decremented = lock.newCondition(); 

public void increment() throws InterruptedException { 
    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     while(increment) 
      decremented.await(); 
     increment = true;   
     c++; 
     System.out.println("increment value: " + c); 
     incremented.signal(); 
    } finally { 
     lock.unlock(); 
    } 

} 

public void decrement() throws InterruptedException { 

    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     while (!increment) 
      incremented.await(); 
     c--; 
     System.out.println("decrement value: " + c); 
     increment = false; 
     decremented.signal(); 
    } finally { 
     lock.unlock(); 
    } 
} 

public int value() { 
    Lock lock = this.lock; 
    lock.lock(); 
    try { 
     return c; 
    } finally { 
     lock.unlock(); 
    } 
} 

} 
+0

¿Puede alguien explicar -1? –

+0

Inicialmente, la respuesta fue menos que útil. Mejor ahora. – Gray

+0

@Gray Proporcionó el código también. –

0

- En primer lugar su increment() y decrement() debe utilizar synchronized palabra clave para evitar la Raza Remítase Regla esta de Brian

When we write a variable which has just been read by another thread, or reading a variable which is just lately written by another thread, must be using Synchronization. And those atomic statements/Methods accessing the fields' data must be also synchronized.

- Es el JVM Thread Scheduler que tiene controlar qué hilo entrará en el estado en ejecución, cuánto tiempo permanecerá allí y adónde irá después de que se haya completado su trabajo.

- Una Cannot be sure de los cuales el hilo se ejecutará primero .....

- También puede utilizar SingleThreadExecutor de java.util.concurrent, esto se completa una tarea antes de pasar a la segunda.

+0

usted cita erróneamente la regla de Brian y no es correcta de todos modos. El uso de volátiles también es una solución. –

+0

@MartinSerrano, en primer lugar, si no tiene una Prueba documentada sobre alguna declaración que sea incorrecta, no la señale mal. En segundo lugar, consulte la 4ª edición del capítulo de Threading de Thinking in Java Book, de Bruce Eikle, si tiene alguna duda ... Ahora la regla de Brian Lo que he escrito aquí es correcto, y creo que aún no ha jugado con la volatilidad suficiente. Hacer que un campo sea volátil no garantiza que las instrucciones que acceden a ese campo sean una declaración atómica individual ... –

Cuestiones relacionadas