user1079425
user1079425

Reputation:

Communication inter 2 Threads

I want to establish communication between 2 threads like this : The first Thread(Sender) sends to the second Thread(Receiver) an Integer and Receiver display the square of this Integer. Here is my code : Carre.java(main) :

public class Carre {
    static Boolean msgArrived = Boolean.FALSE ; 
    static int n ;

    public static void main(String[] args) {
        Thread sender = new Thread(new Sender()) ;
        Thread receiver = new Thread(new Receiver()) ;
        sender.start() ;
        receiver.start() ;
    }

    public int getN() {
        return n;
    }
}

Sender.java :

import java.util.Random;

public class Sender implements Runnable {

    @Override
    public void run() {
        while(Carre.msgArrived == Boolean.TRUE) {
            try {
                wait() ;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i = 0; i < 10; i ++) {
            Random ran = new Random() ; 
            Carre.n = ran.nextInt(100) ;
            Carre.msgArrived = Boolean.TRUE ;
            notifyAll() ;
        }
    }
}

Receiver.java

public class Receiver implements Runnable {

    @Override
    public void run() {
        while(Carre.msgArrived == Boolean.FALSE) {
            try {
                wait() ;
            } 
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Carre.n * Carre.n) ;
        Carre.msgArrived = Boolean.TRUE ;
        notifyAll() ;
    }
}

& When i try to execute my code I receive this error message :

Exception in thread "Thread-1" java.lang.IllegalMonitorStateException

at java.lang.Object.wait(Native Method)

at java.lang.Object.wait(Object.java:502)

at Receiver.run(Receiver.java:12)

at java.lang.Thread.run(Thread.java:636)

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException

at java.lang.Object.notifyAll(Native Method)

at Sender.run(Sender.java:19)

at java.lang.Thread.run(Thread.java:636)

Upvotes: 0

Views: 1579

Answers (4)

Struse
Struse

Reputation: 75

you must call notify() wait() inside synchronized block or method or even class. See race condition of threads in java for why we use synchronized.

Upvotes: 0

erickson
erickson

Reputation: 269857

The error is because you can only call wait() and notify() on objects upon which the current thread is synchronized. The documentation is pretty clear about this.

You should do something like this:

public static void main(String[] args) {
  Object lock = new Object();
  Thread sender = new Thread(new Sender(lock)) ;
  Thread receiver = new Thread(new Receiver(lock)) ;
  sender.start() ;
  receiver.start() ;
}

class Sender implements Runnable {

  private final Object lock;

  Sender(Object lock) { this.lock = lock; }

  @Override
  public void run() {
    synchronized (lock) {
      while(Carre.msgArrived == Boolean.TRUE) {
        try {
          lock.wait() ;
        } catch (InterruptedException ex) {
          /* Interruption is a request to abort operation ASAP. */
          ex.printStackTrace();
          Thread.currentThread().interrupt();
          return;
        }
      }
    }
    ...
  }

Do something similar with the lock for the Receiver, calling lock.notify() within a synchronized(lock) block.

Even better than passing a lock object to the sender and receiver, and writing your own synchronization logic, use a concurrent queue, like SynchronousQueue.

Upvotes: 0

Svilen
Svilen

Reputation: 1447

In my opinion it is better to not use threads directly as they are too low level concurrency entities therefore harder to work with. You should be able to work out your producer/consumer scenario much easier via java.util.concurrent package facilities.

You can have a look here: Producer/Consumer threads using a Queue

Upvotes: 1

aroth
aroth

Reputation: 54856

It's not clear exactly what is being asked here, but I would suggest trying something like the following:

//Carre.java
public class Carre {
    //package level access
    static List<Integer> queue = new ArrayList<Integer>();

    public static void main(String[] args) {
        Thread sender = new Sender();
        Thread receiver = new Receiver();
        sender.start();
        receiver.start();
    }

    //package-level access
    static boolean available() {
        synchronized(queue) {
            return ! queue.isEmpty();
        }
    }

    static int getNext() {
        synchronized(queue) {
            return queue.remove(0);
        }
    }

    static void enqueue(int next) {
        synchronized(queue) {
            queue.add(next);
        }
    }
}

//Sender.java
public class Sender extends Thread {
    private boolean stop = false;

    public void stopRunning() {
        stop = true;
    }

    @Override
    public void run() {
        while (! stop) {
            for(int i = 0; i < 10; i ++) {
                Random ran = new Random() ; 
                Carre.enqueue(ran.nextInt(100));
            }
            try {
                synchronized(Carre.queue) {
                    Carre.queue.notify();
                    Carre.queue.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//Receiver.java
public class Receiver extends Thread {
    private boolean stop = false;

    public void stopRunning() {
        stop = true;
    }

    @Override
    public void run() {
        while(! stop) {
            while (Carre.available()) {
                int next = Carre.getNext();
                System.out.println(next * next) ;
            }
            try {
                synchronized(Carre.queue) {
                    Carre.queue.notify();
                    Carre.queue.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Of course, with the tight coupling between the classes this is far from ideal coding style, but it does demonstrate the basics of how to share data across threads which keeping the producer and consumer threads in sync.

Note that if you are getting a java.lang.IllegalMonitorStateException, it is because you are calling wait() or notify() on an object that you have not synchronized on first. You can synchronize on an object by doing synchronized(object) { //code... }.

Upvotes: 0

Related Questions