0

I am writing a server program that notifies the clients over RMI when there are clients in an ArrayList.

However I can't stop and resume the thread that notifies the client.

Here is my code:

package eu.craenhals;

import java.awt.Dimension;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JFrame;
import javax.swing.JTextArea;

import java.awt.BorderLayout;

public class Server extends JFrame {
    private static final long serialVersionUID = 1L;
    private JTextArea textArea;
    private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy - HH:mm:ss");
    private ServerImpl server;
    private ServerThread thread;

    public Server() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setTitle("Server");
    setSize(new Dimension(521, 333));

    textArea = new JTextArea();
    textArea.setEditable(false);
    getContentPane().add(textArea, BorderLayout.CENTER);

    initialize();
    log("Server opgestart op poort 9878");
    }

    private void initialize() {
    log("Server wordt opgestart");
    try {
        Registry registry = LocateRegistry.createRegistry(9878);
        server = new ServerImpl();
        registry.rebind("server", server);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
    Object lock = new Object();
    thread = new ServerThread(lock);
    thread.start();
    synchronized(lock) {
        try {
        lock.wait();
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
    }
    }

    public static void main(String[] args) {
    Server server = new Server();
    server.setVisible(true);
    }

    private void log(String message) {
    textArea.append(dateFormat.format(new Date()) + " - " + message + "\n");
    }

    class ServerImpl extends UnicastRemoteObject implements ServerInterface {
    private static final long serialVersionUID = 1L;
    private ArrayList<ClientInterface> clients = new ArrayList<ClientInterface>();

    protected ServerImpl() throws RemoteException {
        super();
    }

    private void notifyClients() {
        log("Clients verwittigen");
        for (ClientInterface client : clients) {
        try {
            client.notify("Interface van client " + client.getName() + " updaten");
        } catch (RemoteException e) {
            log(e.getMessage());
        }
        }
    }

    @Override
    public void addClient(ClientInterface client) throws RemoteException {
        if (clients.contains(client)) {
        log("Client '" + client.getName() + "' niet toegevoegd, want bestaat al");
        throw new RemoteException("Client niet toegevoegd, want bestaat al");
        }
        clients.add(client);
        log("Client '" + client.getName() + "' toegevoegd");
    }

    @Override
    public void removeClient(ClientInterface client) throws RemoteException {
        boolean isVerwijderd = clients.remove(client);
        if (isVerwijderd) {
        log("Client '" + client.getName() + "' verwijderd");
        } else {
        log("Client '" + client.getName() + "' niet verwijderd, want bestond niet");
        throw new RemoteException("Client niet verwijderd, want bestond niet");
        }

    }
    }

    class ServerThread extends Thread {
    private final Object lock;

    public ServerThread(Object lock) {
        this.lock = lock;
    }

    public void flag() {
        synchronized (lock) {
        System.out.println("Before Wait");
        try {
            lock.wait();
            System.out.println("After Being Notified");
        } catch (InterruptedException ex) {
            System.out.println("Thread interrupted");
        }
        }
    }

    public void unflag() {
        synchronized (lock) {
        System.out.println("Before Notify All");
        lock.notifyAll();
        System.out.println("After Notify All Method Call");
        }
    }

    public void run() {
        while (true) {
        System.out.println("In serverthread");
        server.notifyClients();
        synchronized (lock) {
            try {
            lock.wait(5000);
            } catch (InterruptedException ex) {
            }
        }
        }
    }
    }
}

I have a ServerThread variable and I start that thread inside the initialize method.

However when I call flag on the thread variable, my whole program is waiting and not only the thread. How can I fix this?

Gray
  • 115,027
  • 24
  • 293
  • 354
Joël Craenhals
  • 475
  • 7
  • 19

1 Answers1

4
  1. wait() will be able to regain lock only when another thread calls notify() on the same object on which wait() was called.

  2. Now according to the above statement, i will try to rectify your problem.

    • First of all create the Object lock = new Object() at the class scope, so the other thread can see it.

    • wait() and notify() must be in synchronized blocks, so put your notify into a synchronized block with the object whose lock is to be released.

      Example:

      synchronized(lock) {
         lock.notify();
      }
      
Gray
  • 115,027
  • 24
  • 293
  • 354
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
  • Nope, doesn't work. When I put the lock object at class scope and I try to call the wait method on the lock in synchronized block, my server frame isn't showing up, so instead of halting the new thread, he is halting the thread that is building my JFrame. – Joël Craenhals Jul 22 '12 at 16:27
  • Keep your EDT (Event Dispatcher Thead) handle only the construction of GUI, dont involve it with the other threads, `public static void main(String[] args){ EventQueue.invokeLater(new Runnable(){ myframe.setVisible(true); }); // Now from here do call other thread }` – Kumar Vivek Mitra Jul 22 '12 at 16:33
  • Hi Gray, your answer is good but most of the content is BOLD. Difficult to grasp by eye at first look. I think Italic font would be appropriate. – Ravindra babu Sep 08 '16 at 11:24