简体   繁体   中英

Using wait() and notify() in multithreading

I am trying wait() , and notify() methods for multi-threading.

I have come up with a small project which I am trying to solve with multi-threading. I have a Taxi, that will reach Rank 6, and I have a Passenger that will reach Rank6.

Taxi will arrive at Rank 6 earlier that Passenger and will wait() for Passenger. When Passenger reaches Rank6, he will notify() .

After getting notified, that Taxi, will continue with the loop and will no to other Ranks.

Taxi.java

package multhithreading.engage.hireForHier;

public class Taxi implements Runnable {

Rank rank = null;

public Taxi(Rank rank) {
    this.rank = rank;
}

public void run() {
    System.out.println(Thread.currentThread().getName() + "  Destined for rank No. " + rank.getRankNo());
    synchronized (rank) {

        for (int i = 1; i < 10; i++) {
            System.out.println("Taxi has reached rank: " + i);
            if (i == 6) {
                try {
                    rank.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }// catch
            }// if

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }// catch

        }// for
    }// synchronized

}// run

}

Passenger.java

package multhithreading.engage.hireForHier;

public class Passenger implements Runnable {

Rank rank = null;

public Passenger(Rank rank) {
    this.rank = rank;
}

public void run() {
    System.out.println(Thread.currentThread().getName() + "  Destined for rank No. " + rank.getRankNo());

    synchronized (rank) {

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

            System.out.println("Passenger has reached rank: " + i);
            if (i == 6) {
                notify();

            }// if
            try {
                Thread.sleep(180);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }// catch

        }// for
    }// synchronized

}// run
}

Rank.java

package multhithreading.engage.hireForHier;


public class Rank {

private int rankNo = 0;

public Rank(int rankNo) {
    this.rankNo = rankNo;
}

public int getRankNo() {
    return rankNo;
}
}

TaxiHire.java

package multhithreading.engage.hireForHier;

public class TaxiHire {

public static void main(String[] args) {

    Rank rank6 = new Rank(6);

    Taxi taxiNo3 = new Taxi(rank6);
    Passenger passengerNo3 = new Passenger(rank6);

    Thread taxi_thread = new Thread(taxiNo3, "taxi_thread");

    Thread passenger_thread = new Thread(passengerNo3, "passenger_thread");

    taxi_thread.start();
    passenger_thread.start();
}

}

The output I am getting is:

taxi_thread  Destined for rank No. 6
Taxi has reached rank: 1
passenger_thread  Destined for rank No. 6
Taxi has reached rank: 2
Taxi has reached rank: 3
Taxi has reached rank: 4
Taxi has reached rank: 5
Taxi has reached rank: 6
Passenger has reached rank: 1
Passenger has reached rank: 2
Passenger has reached rank: 3
Passenger has reached rank: 4
Passenger has reached rank: 5
Passenger has reached rank: 6
Exception in thread "passenger_thread" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at lesson9.engage.hireForHier.Passenger.run(Passenger.java:20)
    at java.lang.Thread.run(Unknown Source)

I need to know why the exception is getting thrown, to me it looks like that the Taxi thread is not getting back the lock. How should this scenario be implemented and how can Taxi thread continue with the loop.

Your help will really be appreciated.

The error is in Passenger class, you synchronize the rand object but notify this object so you code is

if (i == 6) {
                notify();

            }// if

and should be

if (i == 6) {
                try{rank.notify();
                }catch(Exception ex){/*When no any thread is waiting for rank object.*/}

            }// if

also this is possible that taxi thread goes first, so here you will face with exception too, because no any thread is waiting for rank object.

so start the taxi thread first, then start the passenger, the best reliable approach is calling passenger thread with taxi thread. it ensures you taxi thread goes first.

this link may help you with possible situation.

if (i == 6) {
   notify();

Here you are not calling rank.notify() , so the default behavior will try to call notify on this object ( Passenger Object), which will throw IllegalMonitorStateException as you dont hold lock on this

IllegalMonitorStateException occurs when you try to wait() or notify() or notifyAll() on an object without holding lock on that object.

Solution:

if (i == 6) {
   rank.notify();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM