Search code examples
javamultithreadingwebserverpool

Thread pool in a web server in Java


I have my multithread web server and now i wish to implement a thread pool, however even after looking about it i don't get how can i do it in my code :(

Could someone help me get it better? I really need to understand how what i read can be used here, because i don't see the connection and how that works.

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;


public class WebServer {

    static class RequisicaoRunnable implements Runnable {

        private Socket socket;

        RequisicaoRunnable(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                //System.out.println("connection from " + socket.getInetAddress().getHostName());
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //System.out.println("READING SOCKET...");
                String str = in.readLine();
                String[] arr = str.split(" ");
                if (arr != null && arr.length > 2) {
                    while(!str.equals("")) {
                        //System.out.println(str);
                        str = in.readLine();
                    }
                    if (arr[0].equals("GET")) {
                        //System.out.println("REQUESTED RESOURCE: " + arr[1]);
                        String nomeArquivo = arr[1];
                        if (arr[1].startsWith("/")) {
                            nomeArquivo = nomeArquivo.substring(1);
                        }
                        if (nomeArquivo.equals("")) {
                            nomeArquivo = "index.html";
                        }
                        File f = new File(nomeArquivo);
                        if (f.exists()) {
                            FileInputStream fin = new FileInputStream(f);
                            socket.getOutputStream().write("HTTP/1.0 200 OK\n\n".getBytes());
                            byte[] buffer = new byte[1024];
                            int lidos;
                            do {
                                lidos = fin.read(buffer);
                                if (lidos > 0) {
                                    socket.getOutputStream().write(buffer, 0, lidos);
                                }
                            } while (lidos > 0);
                            fin.close();
                        } else {
                            socket.getOutputStream().write("HTTP/1.0 404 Not Found\n\n".getBytes());
                            socket.getOutputStream().write("<html><body>HTTP/1.0 404 File Not Found</body></html>\n\n".getBytes());
                        }
                    } else {
                        socket.getOutputStream().write("HTTP/1.0 501 Not Implemented\n\n".getBytes());
                    }
                }
                socket.close();
            } catch (IOException e) { }
        }
    }

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("waiting connections....");
        while (true) {
            Socket socket = serverSocket.accept();
            RequisicaoRunnable req = new RequisicaoRunnable(socket);
            new Thread(req).start();
        }
    }

}

Solution

  • Idea behind the Thread pool is that create a specified number of threads at start and then assign task to them. Alternatively removing headache of creating threads each time. I was implemented it a little some days ago, here is what I done.

    1. Create some threads at start they share a request queue
    2. Threads are constantly looking for queue and when a request come one of the thread dispatch the request and perform action
    3. The Queue will be synchronized 3.

    Here are some queue methods

    Queue#add();    //add the socket at the end
    Queue#removeFront();//remove socket
    Queue#isEmpty();//boolean if queue is empty
    Queue#size(); //return size of queue
    Queue#getMaxSize();//get maximum allowed size for queue
    

    Your Request processing runnable

    public class Processor implements Runnable {
    
        private Queue<Socket> requests;
        private boolean shut;
    
        Processor(Queue<Socket> requests) {
            this.requests = requests;
            shut = false;
        }
    
        @Override
        public void run() {
            while(!shut) {
                if(requests.isEmpty()) {
                    try{
                        Thread.sleep(#rendomeTimemill);
                    } catch(InterruptedException e){}
                }else {
                    Socket skt = Queue.removeFront();
                    try {
                        //System.out.println("processing request from " + socket.getInetAddress().getHostName());
                        //do you want
                    } catch (Exception e) {
                    } finally {
                        if(skt != null) {
                            try{ skt.close(); skt = null; } catch(IOException ex){}
    
                        }
                    }
                }
            }
        }
        public void stopNow() {
            shut = true;
            Thread.interrupt();
        }
    }
    

    in your main thread create a queue to put requests

    //start your server socket
    Queue<Socket> requests = new Queue<Socket>();
    

    Start worker thread pool

    Precessor []workers = new Processor[NUM_WORKER];
    for(int i=0;i<NUM_WORKER; i++) {
        worker[i] = new Processor(requests);
        Thread th = new Thread(worker[i]);
        th.strat();
    }
    

    in request listening

    //while loope that run forever
    // accept socket
        if(requests.size() == requests.getMaxSize()) {
            socket.getOutputStream().write("HTTP/1.0 505 Error\n\n".getBytes());
            socket.getOutputStream().write("<html><body>Try again</body></html>\n\n".getBytes());
            socket.close();
        } else {
                requests.add(socket);
        }
    

    when you want to shout down server

    for(int i=0;i<NUM_WORKER; i++) {
        worker[i].stopNow();
    }
    

    Note: My concern was not the HTTP headers, so i m not specific, but you must implement the complete HTTP header e.g. Content-type, Content-length etc.