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>