-1

I am trying to make another thread wait in below code but my current thread itself is waiting infinitely. Below are two java classes Server.java that spawns runnable instances of ServerService.java. When such running instance of "ServerService.java" call enqueue method of Server.java.Server.java should make such callee thread wait. But seems my Server.java Thread itself waits infinitely

Server.java

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server{
    private ServerSocket server=null;
    public static Map<Socket,String> clientsConnected=null;
    public static Map<Socket,Runnable> clientsAndThreads=null;
    public static ExecutorService executor=null;
    public static List<Runnable> requestQueue=null;
    public static Map<Runnable,Integer> threadAndRespectiveTime=null;
    /*
     * Contructor
     */
    Server(){
        clientsConnected=new HashMap<Socket,String>();
        clientsAndThreads=new HashMap<Socket,Runnable>();
        threadAndRespectiveTime=new HashMap<>();
        requestQueue=new ArrayList<>();
    }
    /*
     * Accepts connections from clients continually till the server is UP(max 10 clients)
     */
    public void acceptConnection(){
        try{
            executor=Executors.newFixedThreadPool(10);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Socket client=null;
                    while(server.isBound()){
                        try{
                            client=server.accept();
                            DataInputStream di= new DataInputStream(client.getInputStream());
                            String msg=di.readUTF();
                            clientsConnected.put(client, getMessage(msg));
                            ServerWindow.write(msg);
                            Runnable service= new ServerService(client,getMessage(msg));
                            executor.execute(service);
                            clientsAndThreads.put(client, service);
                        }catch(Exception e){
                            System.err.println("error occurred while accepting connections");
                        }
                    }
                }
            }).start();
            System.out.println("now dequeuing");
            while(true){
                dequeue();
            }
        }catch(Exception e){
            System.err.println("Server:error while accepting connections"+e.getMessage());
        }
    }
    public static void enqueue(Socket clientSocket,Integer secondsToWait){
        try{
            Runnable respectiveThread = clientsAndThreads.get(clientSocket);
            threadAndRespectiveTime.put(respectiveThread, secondsToWait);
            System.out.println("making thread wait");
            synchronized (respectiveThread) {
                respectiveThread.wait();
            }
            requestQueue.add(respectiveThread);
            System.out.println("done enqueuing");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static void dequeue() throws InterruptedException{
        while(!requestQueue.isEmpty()){
            Runnable currentThread=requestQueue.get(0);
            Integer timeToWait=threadAndRespectiveTime.get(currentThread);
            Thread.sleep(timeToWait * 1000);
            requestQueue.remove(0);
            System.out.println("wait is complete now notifying thread");
            synchronized (currentThread) {
                currentThread.notify();
            }
        }
    }
    /*
     * This method takes out actual message from http format
     */
    public String getMessage(String str){
        return str.substring(str.indexOf("message:")+8, str.length());
    }
    /*
     * Starts the server listening to port 4000
     */
    public void start_server(){
        try{
            if(server==null || !server.isBound()){
                server = new ServerSocket(4000);
            }
            acceptConnection();
        }catch(Exception e){
            System.err.println("Server:error occurred while server start"+e.getMessage());
        }
    }
    /*
     * Closes client sockets of every connected client, shuts down the thread executor that serves clients
     */
    public void stop_server() throws IOException{
        Iterator it=clientsConnected.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry e= (Map.Entry)it.next();
            Socket toBeClosed=(Socket)e.getKey();
            toBeClosed.close();
        }
        executor.shutdownNow();
        server.close();
    }
}

Below is the class which is spawn as thread by Server.java

ServerService.java

`import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;
/*
 * This class serves the client
 */
public class ServerService extends Server implements Runnable{
    private Socket client=null;
    private String clientBeingServed=null;
    private DataOutputStream dout=null;
    private DataInputStream din=null;
    /*
     * This is construcor that takes client sockte that already has been connected to server and client name.
     * It initializes and input and output streams for serving the respective client
     */
    public ServerService(Socket client,String name) throws IOException {
        this.client=client;
        this.clientBeingServed=name;
        dout=new DataOutputStream(client.getOutputStream());
        din=new DataInputStream(client.getInputStream());
    }
    /*
     * takes out actual message sent by client from its http format
     */
    public String getMessage(String str){
        //System.out.println("returning\n"+str.substring(str.indexOf("message:")+8, str.length()));
        return str.substring(str.indexOf("message:")+8, str.length());
    }
    /*
     * This method converts a message string into HTTP formatted string
     */
    public String getHttpMessage(String msg){
        String str="POST Http/1.1 \n" + "Host: www.uta.com \n" + "User-Agent: Mozilla/5.0 \n"
                + "Content=type: application/x-www-form-urlencoded \n" + "Content-Length: " + msg.length() + " \n"
                + "Date:" + new Date() + " \n" + "message:" + msg;
        return str;
    }
    /*
     * This method execute when thread for this class is executed from Server.java file after connection is accepted
     */
    @Override
    public void run() {
        int waitTime=0;
        try{
            while(client.isConnected()){
                    String msg=din.readUTF();
                    ServerWindow.write(msg);
                    waitTime=Integer.parseInt(getMessage(msg));
                    System.out.println("Equeing:"+clientBeingServed);
                    Server.enqueue(client, waitTime);
                    ServerWindow.write("Served client:"+clientBeingServed);
                    dout.writeUTF(getHttpMessage("Server waited "+waitTime+" seconds for "+clientBeingServed));
                    dout.flush();
            }
            client.close();
        }catch(Exception e){
            System.err.println("ServerService:error serving client"+clientBeingServed+e.getMessage());
        }
    }
}`
nikhil kekan
  • 532
  • 3
  • 16
  • What exactly are you trying to wait for? Where's the code that checks if the thing you are waiting for has happened? – David Schwartz Oct 31 '18 at 23:06
  • 1
    When you call `wait()`, it suspends the current thread. – shmosel Oct 31 '18 at 23:07
  • enqueue method is member of a class that spawns threads, i am trying to make such spawn thread wait. – nikhil kekan Oct 31 '18 at 23:09
  • Why not write wait() in child thread and notify() from enqueue thread? – Sahil Dhoked Oct 31 '18 at 23:16
  • @nikhilkekan Wait for wait? – David Schwartz Oct 31 '18 at 23:25
  • @sahilDhoked : wait() method will make the thread wait and notify() will wake it up, as per documentation. – nikhil kekan Oct 31 '18 at 23:28
  • @nikhilkekan You call the `wait` method without doing any checks whether it makes sense to wait for something. What are you waiting for? Where's the code to ensure that it hasn't already happened? Where's the code to wake any waiting threads when the thing they are waiting for happens? – David Schwartz Oct 31 '18 at 23:34
  • @davidSchwartz : I havent written it yet, because i see it stuck. I could see in debug that the thread is alive, i can even see that it control is coming to enqueue method its just that instead of making the callee thread wait, the Server.java thread is waiting until i terminate it – nikhil kekan Oct 31 '18 at 23:39
  • @davidschwartz : I am trying to go step by step ahead, Please kindly suggest best way to control spawned runnable instances – nikhil kekan Nov 01 '18 at 00:09
  • What you want is more like an interrupt. You cannot stop and start a thread mid execution. – Sahil Dhoked Nov 01 '18 at 01:54
  • Read the _[Guarded Blocks Tutorial](https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)_ if you want to understand how `wait()` and `notify()/notifyAll()` are supposed to be used. – Solomon Slow Nov 01 '18 at 16:00
  • I'm voting to close this question as off-topic because it's a low-level question, based on a higher-level misunderstanding of how threads should interact with one another. – Solomon Slow Nov 01 '18 at 16:02

1 Answers1

0

Instead of calling wait on spawned thread, My ServerService thread instance waits itself after calling enqueue method of Server.java. Then later Server.java calls notify to resume ServerService thread.

Server.java

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;

public class Server{
    private ServerSocket server=null;
    public static Map<Socket,String> clientsConnected=null;
    public static Map<Socket,Runnable> clientsAndThreads=null;
    public static ExecutorService executor=null;
    public static Queue<Thread> requestQueue=null;
    public static Map<Thread,Integer> threadAndRespectiveTime=null;
    /*
     * Contructor
     */
    Server(){
        clientsConnected=new HashMap<Socket,String>();
        clientsAndThreads=new HashMap<Socket,Runnable>();
        threadAndRespectiveTime=new HashMap<>();
        requestQueue=new LinkedList<>();
    }
    /*
     * Accepts connections from clients continually till the server is UP(max 10 clients)
     */
    public void acceptConnection(){
        try{
            executor=Executors.newFixedThreadPool(10);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Socket client=null;
                    while(server.isBound()){
                        try{
                            client=server.accept();
                            DataInputStream di= new DataInputStream(client.getInputStream());
                            String msg=di.readUTF();
                            clientsConnected.put(client, getMessage(msg));
                            ServerWindow.write(msg);
                            Runnable service= new ServerService(client,getMessage(msg));
                            executor.execute(service);
                        }catch(Exception e){
                            System.err.println("error occurred while accepting connections");
                        }
                    }
                }
            }).start();
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        while(true){
                            Server.dequeue();
                        }
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }).start();
        }catch(Exception e){
            System.err.println("Server:error while accepting connections"+e.getMessage());
        }
    }
    public static synchronized void enqueue(Thread t,Integer secondsToWait){
        try{
            System.out.println(requestQueue );
            threadAndRespectiveTime.put(t, secondsToWait);
            requestQueue.add(t);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static synchronized void dequeue() throws InterruptedException{
        while(!requestQueue.isEmpty()){
            Thread currentThread=requestQueue.remove();
            Integer timeToWait=threadAndRespectiveTime.get(currentThread);
            System.out.println("time to wait is:"+timeToWait);
            Thread.currentThread().sleep(timeToWait * 1000);
            synchronized (currentThread) {
                currentThread.notify();
            }
        }
    }
    /*
     * This method takes out actual message from http format
     */
    public String getMessage(String str){
        return str.substring(str.indexOf("message:")+8, str.length());
    }
    /*
     * Starts the server listening to port 4000
     */
    public void start_server(){
        try{
            if(server==null || !server.isBound()){
                server = new ServerSocket(4000);
            }
            acceptConnection();
        }catch(Exception e){
            System.err.println("Server:error occurred while server start"+e.getMessage());
        }
    }
    /*
     * Closes client sockets of every connected client, shuts down the thread executor that serves clients
     */
    public void stop_server() throws IOException{
        Iterator it=clientsConnected.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry e= (Map.Entry)it.next();
            Socket toBeClosed=(Socket)e.getKey();
            toBeClosed.close();
        }
        executor.shutdownNow();
        server.close();
    }
}

ServerService.java

==================

    import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;
/*
 * This class serves the client
 */
public class ServerService extends Server implements Runnable{
    private Socket client=null;
    private String clientBeingServed=null;
    private DataOutputStream dout=null;
    private DataInputStream din=null;
    /*
     * This is construcor that takes client sockte that already has been connected to server and client name.
     * It initializes and input and output streams for serving the respective client
     */
    public ServerService(Socket client,String name) throws IOException {
        this.client=client;
        this.clientBeingServed=name;
        dout=new DataOutputStream(client.getOutputStream());
        din=new DataInputStream(client.getInputStream());
    }
    /*
     * takes out actual message sent by client from its http format
     */
    public String getMessage(String str){
        //System.out.println("returning\n"+str.substring(str.indexOf("message:")+8, str.length()));
        return str.substring(str.indexOf("message:")+8, str.length());
    }
    /*
     * This method converts a message string into HTTP formatted string
     */
    public String getHttpMessage(String msg){
        String str="POST Http/1.1 \n" + "Host: www.uta.com \n" + "User-Agent: Mozilla/5.0 \n"
                + "Content=type: application/x-www-form-urlencoded \n" + "Content-Length: " + msg.length() + " \n"
                + "Date:" + new Date() + " \n" + "message:" + msg;
        return str;
    }
    /*
     * This method execute when thread for this class is executed from Server.java file after connection is accepted
     */
    @Override
    public void run() {
        int waitTime=0;
        try{
            while(client.isConnected()){
                    String msg=din.readUTF();
                    ServerWindow.write(msg);
                    waitTime=Integer.parseInt(getMessage(msg));
                    System.out.println("Equeing:"+clientBeingServed);
                    Server.enqueue(Thread.currentThread(), waitTime);
                    System.out.println("before going to sleep");
                    synchronized (Thread.currentThread()) {
                        Thread.currentThread().wait();
                    }
                    System.out.println("after sleeping");
                    ServerWindow.write("Served client:"+clientBeingServed);
                    dout.writeUTF(getHttpMessage("Server waited "+waitTime+" seconds for "+clientBeingServed));
                    dout.flush();
            }
            client.close();
        }catch(Exception e){
            System.err.println("ServerService:error serving client"+clientBeingServed+e.getMessage());
        }
    }
}
nikhil kekan
  • 532
  • 3
  • 16