Stop threads in Java

1

In summary mode, the result I get now is:

Miembro_X esta mirando el canal ...
Miembro_X esta mirando el canal ...
Miembro_X esta mirando el canal ...
Ja nadie mira la tv.

Code:

CASA CLASS:

public class Casa {

    public static void main(String[] args) throws InterruptedException {
        Comandament c = new Comandament();
        int numMembres = 5; //total familia

        UnitatFamiliar[] membre = new UnitatFamiliar[numMembres];
            for(int i=0; i<numMembres; i++) {
            membre[i] = new UnitatFamiliar(c);
            membre[i].setName("Miembro_"+i);
            membre[i].start();
        }

        for(int i=0; i<numMembres; i++) {
            membre[i].join();
        }

        System.out.println("Nadie mira la tv");
    }
}

UNIDADEFAMILIA CLASS

public class UnitatFamiliar extends Thread {
    Comandament comandament;
    static int canal;
    public UnitatFamiliar(Comandament c) {
        comandament = c;
        canal = 0;
    }
    @Override
    public void run() {

        comandament.Agafa();
        int canal = (int) ((Math.random() * 100) + 1); 
        System.out.println(getName() + " esta mirando el canal " + canal);
        //Mirar la tele
        try {

            Thread.sleep((long) (Math.random() * 350) + 300);  
        } catch (InterruptedException e) {
            System.out.println("Error!!!");
        }
        //Dejaa el mando
        comandament.Deixa();
    }
}

From here, the new class that is:

COMANDAMENT, with two methods Agafa() and Deixa() :

public class Comandament {

    private boolean avalible = false;

    Comandament() {}

    void Agafa() {
        while (avalible == false) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        avalible = false;
        notify();
    }

    void Deixa() {}
}

I need that the users when they take the comandament "mando de la tv" , only they can take it during X time (in this case it is already implanted Thread.sleep((long) (Math.random() * 350) + 300); in the class UnitatFamiliar .

That is to say that when another one watches the same channel, the program will not say anything, but when it changes of channel it must warn.

I'm pretty lost. Can you help me?

    
asked by Montse Mkd 28.02.2018 в 20:56
source

1 answer

1

The truth is that you were on track. By parts:

Main: House

In the main you initialize 5 threads and you pass them all the same object Comandament that corresponds to the only shared resource that the threads compete to obtain.

        Comandament c = new Comandament();
        int numMembres = 5; //total familia

        UnitatFamiliar[] membre = new UnitatFamiliar[numMembres];
        for (int i = 0; i < numMembres; i++) {
            membre[i] = new UnitatFamiliar(c);
            membre[i].setName("Miembro_" + i);
            membre[i].start();
        }

Then, you correctly expect all threads to end next to the main thread, making them join()

        for (int i = 0; i < numMembres; i++) {
            membre[i].join();
        }

        System.out.println("Nadie mira la tv");

Threads: UnitatFamiliar

In each thread, you use a method to request the exclusivity of the command command:

@Override
public void run() {

    comandament.Agafa();

Then you perform the logic once this resource is obtained.

    int canal = (int) ((Math.random() * 100) + 1);
    System.out.println(getName() + " esta mirando el canal " + canal);
    //Mirar la tele
    try {

        Thread.sleep((long) (Math.random() * 350) + 300);
    } catch (InterruptedException e) {
        System.out.println("Error!!!");
    }

And finally you release the resource

    //Dejaa el mando
    comandament.Deixa();
}

Shared resource: Comandament

Given the previous code, it is required that comandament implement 2 methods:

  • Agafa() : You must block the thread and get the resource exclusively for whoever calls it, only return once the resource gets
  • Deixa() : You must release the resource
  • The way to implement the above is to make use of a lock , allowing only one thread to have said lock .

    Starting with your original implementation:

    public class Comandament {
        private boolean avalible = false;
    
        Comandament() {}
    
        void Agafa() {
            while (avalible == false) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            avalible = false;
            notify();
        }
    
        void Deixa() {}
    }
    

    The first error is that the control starts unavailable, when the original state should be available:

    private boolean avalible = true;
    

    The second error is that in the method Agafa() you are not getting any lock and you are also invoking wait() and notify() without having the intrinsic lock of the current object. One way to do this, is to simply do the full method synchronized :

    synchronized void Agafa() {
        while (avalible == false) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        avalible = false;
        notify();
    }
    

    And with that already fulfilling what is asked to the method, only 1 thread can get the resource, and blocks the execution while the current thread can not get it.

    Finally, obviously the 3rd error is that there is no implementation to release the resource. It is enough to leave the resource available and notify the other threads:

    synchronized void Deixa() {
        avalible = true;
        notify();
    }
    

    And smart, that's what you were missing, you can watch TV:

    Miembro_0 esta mirando el canal 95
    Miembro_1 esta mirando el canal 62
    Miembro_3 esta mirando el canal 62
    Miembro_2 esta mirando el canal 32
    Miembro_4 esta mirando el canal 60
    Nadie mira la tv
    
        
    answered by 01.03.2018 / 19:51
    source