Java - Thread Synchronization Questions

Asked

Viewed 71 times

1

I have the following classes:

Vehicle (Vehicle):

public class Vehicle {

    private String chassis;
    private String type;
    private double topSpeed;

    public Vehicle() {

    }

    public Vehicle(String chassis, String type, double topSpeed) {
        super();
        this.chassis = chassis;
        this.type = type;
        this.topSpeed = topSpeed;
    }

    public void clean() {
        System.out.println(">> O veículo do tipo [" + getType() + "] está sendo limpo.");
    }

    public void adjust() {
        System.out.println(">> O veículo do tipo [" + getType() + "] está sendo ajustado.");
    }

    public int incrementalSpeed(int value) {
        return (int) (value + getTopSpeed());
    }

    public String getChassis() {
        return chassis;
    }

    public String getType() {
        return type;
    }

    public double getTopSpeed() {
        return topSpeed;
    }

    public void setTopSpeed(double topSpeed) {
        this.topSpeed = topSpeed;
    }

}

Competitor (Competitor):

public class Competitor implements Runnable {

    private Vehicle vehicle;
    private String name;
    private int pitStopTime;

    public Competitor(Vehicle vehicle, String name) {
        super();
        this.vehicle = vehicle;
        this.name = name;
    }

    @Override
    public void run() {
        startRace();
    }

    public void startRace() {
        synchronized(this) {
            System.out.println(">> O veículo de nome " + getName() + " e do tipo " + vehicle.getType() + " iniciou a corrida.");

            try {
                for(int i = 1; i <= 5; i++) {
                    if(i == 1) {
                        System.out.println(">> O veículo de nome " + getName() + " e do tipo " + vehicle.getType() + " acabou de percorrer sua primeira volta.");

                        if(vehicle.getType().equalsIgnoreCase("Carro")) {
                            setPitStopTime(1500);
                            Thread.sleep(getPitStopTime());
                        } else {
                            setPitStopTime(950);
                            Thread.sleep(getPitStopTime());
                        }
                    } else {
                        System.out.println(">> O veículo de nome " + getName() + " e do tipo " + vehicle.getType() + " percorreu " + i + " voltas.");
                    }
                }
            } catch(InterruptedException exception) {
                System.out.println(">> O veículo de nome " + getName() + " e do tipo " + vehicle.getType() + " teve um problema durante a volta.");
            }

            System.out.println(">> O veículo de nome " + getName() + " e do tipo " + vehicle.getType() + " terminou a corrida.");
        }
    }

    public String getName() {
        return name;
    }

    public void setPitStopTime(int pitStopTime) {
        this.pitStopTime = pitStopTime;
    }

    public int getPitStopTime() {
        return pitStopTime;
    }

}

Race (Race):

public class Race {

    public static void main(String[] args) {
        Thread firstCompetitor = new Thread(new Competitor(new Vehicle(null, "Bicicleta", 5), "Aitor"));
        Thread secondCompetitor = new Thread(new Competitor(new Vehicle(null, "Carro", 5), "Anderson"));
        Thread thirdCompetitor = new Thread(new Competitor(new Vehicle(null, "Carro", 5), "Gabriel"));
        Thread fourthCompetitor = new Thread(new Competitor(new Vehicle(null, "Bicicleta", 5), "Eduardo"));
        Thread fifthCompetitor = new Thread(new Competitor(new Vehicle(null, "Bicicleta", 5), "Angela"));
        Thread sixthCompetitor = new Thread(new Competitor(new Vehicle(null, "Carro", 5), "José"));

        firstCompetitor.start();
        secondCompetitor.start();
        thirdCompetitor.start();
        fourthCompetitor.start();
        fifthCompetitor.start();
        sixthCompetitor.start();
    }

}

If it is a race with several competitors (which are vehicles), each competitor has a name and a time of Pitstop, if it is a car, the time is 1500 milliseconds, if it is a bike, 950 milliseconds.

I used a synchronization block in my startRace() method but nothing happens. According to my knowledge of Threads synchronization, the Thread calling the method will only run when the Thread calling the method first finishes running.

I managed to execute the way I’d like it to run through this way:

try {
    firstCompetitor.start();
    firstCompetitor.join();

    secondCompetitor.start();
    secondCompetitor.join();

    thirdCompetitor.start();
    thirdCompetitor.join();

    fourthCompetitor.start();
    fourthCompetitor.join();

    fifthCompetitor.start();
    fifthCompetitor.join();

    sixthCompetitor.start();
    sixthCompetitor.join();
} catch(InterruptedException exception) {
    System.out.println(exception.toString());
}

But I would like to sync through the syncronized(this) block. I read in some topics on the internet that to make it work you must lock the object that we want to synchronize, causing the instance that will run the method to traverse until the instance you called first finishes executing.

1 answer

0

I’ll be brief that I’m on the cell phone.

With Join() it’s wrong because threads run one at a time and that’s not what you want.

Your code has two other errors.

First, the Synchronized block is being the entire race of each vehicle (it’s out of the for, it should be in).

Second, you have to synchronize on the same object. You are synchronizing on this, only that each Competitor is a different object and therefore there is no dispute for resources.

  • Ah, I understand. I’m going to fix that first part that’s wrong. Regarding the second error, how could I synchronize the same object? I tried to pass an object of Competitor, but in main returns me an exception.

  • I’ll make a suggestion that’s not very pretty, but it’s the best I can think of at the moment: create a global class variable (public Static final Object) and use it in Synchronized. Your design of the last two classes is wrong, but I can’t see it now.

  • Get it done the way you said. I also managed to pass as parameter in Synchronized my class, this way: Class.forName("Competitors"); However, after doing several tests, I realized that synchronization is not 100% accurate. There are times when firstCompetitor (which you called first) is the first to run, and there are times when secondCompetitor.

  • New questions, new questions.

  • And do not forget to accept this answer, if she has answered you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.