Java: Problems with Wait() and notify()

Asked

Viewed 366 times

2

Good evening, I’m doing a java project where I make connections between the client and a server. This client sends Messages to another recipient. It is up to the Server to handle this message by forwarding it to the right Client. I’m making a mistake:

Exception in thread "Thread-4" java.lang.Illegalmonitorstateexception at java.lang.Object.Wait(Native Method) at java.lang.Object.Wait(Object.java:502) at network.WorkerRunnableOut.run(Workerrunnableout.java:34) at java.lang.Thread.run(Thread.java:745)

Which happens right after connecting the Client to the server. I then leave some of my code to understand where the error comes from.

public class WorkerRunnableOut implements Runnable{

protected Socket clientSocket = null;
protected String serverText = null;
protected ServerMulti server;
ArrayList <Message> msmDelevery;

public WorkerRunnableOut(ServerMulti server, Socket clientSocket, String serverText) {
    this.clientSocket = clientSocket;
    this.serverText = serverText;
    this.server = server;
    msmDelevery = new ArrayList<Message>();
}

public void run() {
    try {
        ObjectOutputStream output = new ObjectOutputStream(clientSocket.getOutputStream());
        long time = System.currentTimeMillis();
        output.write(("HTTP/1.1 200 OK\n\nWorkerRunnable: " +
                this.serverText + " - " +
                time +
                "").getBytes());
        while(msmDelevery.isEmpty()) {
            System.out.println("Servidor : nenhuma mensagem para entregar");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }   
        for(int i = 0; i<server.msgToDelevery.size(); i++){
            if(msmDelevery.get(i)!=null) {
                Message m = msmDelevery.get(i);
                String id = msmDelevery.get(i).getDest();
                if(server.clientesOn.containsKey(id)) {
                    server.clientesOn.get(id).sendMessage(output, m);
                }

            }



        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void sendMessage(ObjectOutputStream o, Message m) {
    // TODO Auto-generated method stub
    try {
        o.writeObject(m);
        o.flush();
    } catch (IOException e) {
        System.out.println("Erro ao enviar para o cliente");
    }

}

public void addMessage(Message m) {
    msmDelevery.add(m);
    notify();
}

}

.

public class WorkerRunnableIn implements Runnable {
protected Socket clientSocket = null;
protected String serverText = null;
protected ServerMulti server;

public WorkerRunnableIn(ServerMulti server, Socket clientSocket, String serverText) {
    this.clientSocket = clientSocket;
    this.serverText = serverText;
    this.server = server;

}

public void run() {
    try {
        ObjectInputStream input = new ObjectInputStream(clientSocket.getInputStream());

        WorkerRunnableOut wout = new WorkerRunnableOut(server, clientSocket, serverText);
        new Thread(wout).start();

        while (true) {
            Message m = (Message) input.readObject();
            System.out.println("Teste de m >>> " + m);
            if(m.getDest()==null) {
                String usernames = m.getUser();
                server.clientesOn.put(usernames, wout);
                System.out.println("Adicionei " + usernames + " à lista de clientes On");
            }
            else {
                wout.addMessage(m);
                System.out.println("Entrei aqui");
            }
        }

    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Thank you

1 answer

2

As described in documentation, to use wait and notify you need to synchronize the object on which you are running the methods.

Example:

synchronized (obj) {
    obj.wait();
}

In your case, if you are calling the methods implicitly in the object itself, you must synchronize the this.

Example:

synchronized (this) {
    wait();
}

The same for the notify.

The mistake IllegalMonitorStateException occurs because Java has an object monitor that controls synchronization. To avoid competition issues with multiple threads trying to wait or notify objects, this monitor requires the thread calling these methods to have the "right" of access to the synchronized object, which is done through the synchronized. Without synchronizing, the monitor denies access to methods with the exception.

Note: my answer does not mean that there are no other possible problems in this implementation.

  • 1

    thanks for the reply. I have already managed to get this to work.

  • @Javanab you have the code of these two classes with the right corrections you can send me?

Browser other questions tagged

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