Java: Problems with wait () and notify ()

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, forwarding it to the right Client. I am an error:

  

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)

What happens soon after connecting the Client to the server. I then leave some of my code to see 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

    
asked by anonymous 05.12.2015 / 22:50

1 answer

2

As described in the documentation , to use wait and notify you need to synchronize the object on which you are executing 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();
}

Same for notify .

The IllegalMonitorStateException error occurs because Java has an object monitor that controls synchronization. To avoid competing problems with multiple threads attempting to wait or notify objects, this monitor requires that the thread calling those methods has the "right" access to the object synchronized, which is done through synchronized . Without synchronizing, the monitor denies access to methods with the exception.

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

    
07.12.2015 / 04:26