Site Search:

6.2 The Executor framework Example

TaskExecutionWebServer replaces the hard-coded thread creation with an Executor. Executors.newFixedThreadPool uses a thread pool with 2 threads.

DemoSever>cat DemoWebServer.java 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class DemoWebServer {
    private static final int NTHREADS = 2;
    private static final Executor exec
            = Executors.newFixedThreadPool(NTHREADS);
    
    public static void main(String[] args) throws IOException {
        
        try(ServerSocket socket = new ServerSocket(8090)) {
            while (true) {
                Socket connection = socket.accept();
                //handleRequest(connection);
                //new Thread(() -> handleRequest(connection)).start();
                exec.execute(() -> handleRequest(connection));
            }
        }
    }

    private static void handleRequest(Socket connection) {
        System.out.println(Thread.currentThread().toString() + connection.getInetAddress());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


DemoSever>javac DemoWebServer.java 
DemoSever>java DemoWebServer
Thread[pool-1-thread-2,5,main]/0:0:0:0:0:0:0:1
Thread[pool-1-thread-1,5,main]/0:0:0:0:0:0:0:1
Thread[pool-1-thread-2,5,main]/0:0:0:0:0:0:0:1
Thread[pool-1-thread-1,5,main]/0:0:0:0:0:0:0:1
Thread[pool-1-thread-1,5,main]/0:0:0:0:0:0:0:1




DemoClient>date;for i in {1..5}; do curl localhost:8090& done;wait;date
Sat Jul 22 20:18:59 EDT 2017
[1] 2138
[2] 2139
[3] 2140
[4] 2141
[5] 2142
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
[1]   Exit 52                 curl localhost:8090
[2]   Exit 52                 curl localhost:8090
[3]   Exit 52                 curl localhost:8090
[4]-  Exit 52                 curl localhost:8090
curl: (52) Empty reply from server
[5]+  Exit 52                 curl localhost:8090
Sat Jul 22 20:19:05 EDT 2017
DemoClient>


Instead of use Executors to get standard Executor implementations, we can write customized Executor implementations. ThreadPerTaskExecutor creates a new thread for each request.

DemoSever>cat DemoWebServer.java 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;

public class DemoWebServer {
    //private static final Executor exec = Executors.newFixedThreadPool(2);
    final static Executor exec = new Executor() {
        @Override
        public void execute(Runnable r) {
            new Thread(r).start();   //Thread Per TaskExecutor
        }
    };
    
    public static void main(String[] args) throws IOException {
        
        try(ServerSocket socket = new ServerSocket(8090)) {
            while (true) {
                Socket connection = socket.accept();
                exec.execute(() -> handleRequest(connection));
            }
        }
    }

    private static void handleRequest(Socket connection) {
        System.out.println(Thread.currentThread().toString() + connection.getInetAddress());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
DemoSever>javac DemoWebServer.java 
DemoSever>java DemoWebServer
Thread[Thread-0,5,main]/0:0:0:0:0:0:0:1
Thread[Thread-4,5,main]/0:0:0:0:0:0:0:1
Thread[Thread-3,5,main]/0:0:0:0:0:0:0:1
Thread[Thread-2,5,main]/0:0:0:0:0:0:0:1
Thread[Thread-1,5,main]/0:0:0:0:0:0:0:1

^C


DemoClient>date;for i in {1..5}; do curl localhost:8090& done;wait;date
Sat Jul 22 20:29:23 EDT 2017
[1] 2155
[2] 2156
[3] 2157
[4] 2158
[5] 2159
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
[1]   Exit 52                 curl localhost:8090
[2]   Exit 52                 curl localhost:8090
[3]   Exit 52                 curl localhost:8090
[4]-  Exit 52                 curl localhost:8090
[5]+  Exit 52                 curl localhost:8090
Sat Jul 22 20:29:25 EDT 2017
DemoClient>


As another example of customized Executor implementation. WithinThreadExecutor behave like the single-threaded version.

DemoSever>cat DemoWebServer.java 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;

public class DemoWebServer {
    //private static final Executor exec = Executors.newFixedThreadPool(2);
    final static Executor exec = new Executor() {
        @Override
        public void execute(Runnable r) {
            //new Thread(r).start();   //Thread Per TaskExecutor
            r.run();  //single threaded
        }
    };
    
    public static void main(String[] args) throws IOException {
        
        try(ServerSocket socket = new ServerSocket(8090)) {
            while (true) {
                Socket connection = socket.accept();
                exec.execute(() -> handleRequest(connection));
            }
        }
    }

    private static void handleRequest(Socket connection) {
        System.out.println(Thread.currentThread().toString() + connection.getInetAddress());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
DemoSever>javac DemoWebServer.java 
DemoSever>java DemoWebServer
Thread[main,5,main]/0:0:0:0:0:0:0:1
Thread[main,5,main]/0:0:0:0:0:0:0:1
Thread[main,5,main]/0:0:0:0:0:0:0:1
Thread[main,5,main]/0:0:0:0:0:0:0:1
Thread[main,5,main]/0:0:0:0:0:0:0:1

^C



DemoClient>date;for i in {1..5}; do curl localhost:8090& done;wait;date
Sat Jul 22 20:32:09 EDT 2017
[1] 2169
[2] 2170
[3] 2171
[4] 2172
[5] 2173
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
curl: (52) Empty reply from server
[1]   Exit 52                 curl localhost:8090
[2]   Exit 52                 curl localhost:8090
[3]   Exit 52                 curl localhost:8090
[4]-  Exit 52                 curl localhost:8090
curl: (52) Empty reply from server
[5]+  Exit 52                 curl localhost:8090
Sat Jul 22 20:32:19 EDT 2017
DemoClient>