concurrency java threads

1

I'm playing the thread theme in java and I'm doing some checks. I want to extract and enter the letters in the pipeline array two by two in a concurrent way and that every time that letters enter or exit I indicate the ones that come out and how many are left in the pipe array.

The code I have is this:

class ProductorConsumidorTuberia {

    public static void main(String args[]) {

        Tuberia t = new Tuberia();          // creación de la tubería
        Productor p = new Productor(t);     // creación del productor, recibe la tubería como parámetro
        Consumidor c = new Consumidor(t);   // creación del consumidor, recibe la tubería como parámetro

        p.start();      // se lanza el hilo productor
        c.start();      // se lanza el hilo consumidor
    }
}


class Productor extends Thread {

    private Tuberia tuberia;
    private String alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public Productor(Tuberia t) {           // constructor

            // Mantiene una copia propia del objeto compartido t
            tuberia = t;

    }

    public void run() {

        char c; // almacenará una letra individual


        // Mete 10 letras en la tubería
        for (int i = 0; i < 10; i++) {

            c = alfabeto.charAt((int) (Math.random() * 26)); // letra del alfabeto al azar

            tuberia.introducir(c);

// Imprime un registro con lo añadido

            System.out.println("Introducida la letra " + c + " a la tuberia.");

// Espera un poco antes de añadir más letras

            try {
                    sleep((int) (Math.random() * 100));

            } catch (InterruptedException e) {

                e.printStackTrace();
            }
        }

    }

}


class Consumidor extends Thread {

    private Tuberia tuberia;

    public Consumidor(Tuberia t) {

        tuberia = t;        // Mantiene una copia propia del objeto compartido

    }

    public void run() {

        char c;

// Consume 10 letras de la tubería

        for (int i = 0; i < 10; i++) 
        {

            c = tuberia.recuperar();  // recupera una letra desde la tubería a través del método sincronizado RECUPERAR

            // Imprime la letra recuperada
            System.out.println("Recuperada la letra " + c);

            // Espera un poco antes de seguir cogiendo más letras (al azar, como máximo 2000ms )
            try {
                        sleep((int) (Math.random() * 2000));

            } catch (InterruptedException e) {

                e.printStackTrace();
            }

        }

    }

}

class Tuberia {

    private char buffer[] = new char[6];

    private int siguiente = 0;

    // banderas para saber el estado del buffer
    private boolean estaLlena = false;
    private boolean estaVacia = true;

    // Método SINCRONIZADO para retirar letras del buffer
    public synchronized char recuperar() {

        // IMPORTANTE: NO se puede consumir si el buffer está vacío
        while (estaVacia == true) {

            try {
                    wait(); // Se sale cuando estaVacia cambia a false

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        // Decrementa la cuenta, ya que va a consumir una letra

        siguiente--;

        // Comprueba si se retiró la última letra

        if (siguiente == 0)     estaVacia = true;

        // El buffer no puede estar lleno, porque acabamos de consumir
        estaLlena = false;

        notify();  //se notifica al monitor de sincronización para ejecute el siguiente hilo en espera (que esté en WAIT), productor o consumidor


        // Devuelve la letra al thread consumidor
        return (buffer[siguiente]);
    }


    // Método SINCRONIZADO para meter letras por la tubería
    public synchronized void introducir(char c) {

        // Espera hasta que haya sitio para otra letra

        while (estaLlena == true) {

            try {
                    wait(); // Se sale cuando estaLlena cambia a false

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        // Añade una letra en el primer lugar disponible
        buffer[siguiente] = c;

        // Cambia al siguiente lugar disponible
        siguiente++;

        // Comprueba si el buffer está lleno
        if (siguiente == 6)     estaLlena = true;

        estaVacia = false; // no puede estar vacía porque se acaba de meter una letra

        notify();  //se notifica al monitor de sincronización para ejecute el siguiente hilo en espera (que esté en WAIT), productor o consumidor

    }

}
    
asked by Juan 30.10.2018 в 11:20
source

1 answer

1

I've done it and I have not had any problems.

To be able to identify who produces and who consumes, I have introduced slight changes in the code (basically giving attributes such as name to the consumer and being able to create the alphabet through the constructor for the case of the producer).

This is the class code released by producers and consumers:

public class ProductorConsumidorTuberia {

    public static void main(String args[]) {
        // creación de la tubería
        Tuberia t = new Tuberia(); 

        // creación del productor, recibe la tubería como parámetro
        Productor p = new Productor(t,"p","ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        // creación del productor2, recibe la tubería como parámetro
        Productor p2 = new Productor(t,"p2","1234567890");    

        // creación del consumidor, recibe la tubería como parámetro    
        Consumidor c = new Consumidor(t,"c");
        // creación del consumidor 2, recibe la tubería como parámetro      
        Consumidor c2 = new Consumidor(t,"c2");   

        p.start();      // se lanza el hilo productor
        p2.start();      // se lanza el hilo productor2
        c.start();      // se lanza el hilo consumidor
        c2.start();      // se lanza el hilo consumidor2
    }

}

To be able to visualize the pipe content simply implement the toString method of the Pipe class and execute it, for example, every time a character is entered in the buffer.

The toString method is very simple:

public String toString() {
    return "Tuberia buffer=" + Arrays.toString(buffer);
}

Greetings.

    
answered by 30.10.2018 в 12:16