1、
package multiThread.art;
public interface ThreadPool<HttpRequestHandler> {
// 执行一个HttpRequestHandler ,这个HttpRequestHandler需要实现Runnable
void execute(HttpRequestHandler httpRequestHandler);
// 关闭线程池
void shutdown();
// 增加工作者线程
void addWorkers(int num);
// 减少工作者线程
void removeWorker(int num);
// 得到正在等待执行的任务数量
int getJobSize();
}
package multiThread.art;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
public class DefaultThreadPool<HttpRequestHandler extends Runnable> implements ThreadPool<HttpRequestHandler> {
// 线程池最大限制数
private static final int MAX_WORKER_NUMBERS = 10;
// 线程池默认的数量
private static final int DEFAULT_WORKER_NUMBERS = 5;
// 线程池最小的数量
private static final int MIN_WORKER_NUMBERS = 1;
// 这是一个工作列表,将会向里面插入工作
private final LinkedList<HttpRequestHandler> jobs = new LinkedList<HttpRequestHandler>();
// 工作者列表
private final List<Worker> workers = Collections.synchronizedList(new
ArrayList<Worker>());
// 工作者线程的数量
private int workerNum = DEFAULT_WORKER_NUMBERS;
// 线程编号生成
private AtomicLong threadNum = new AtomicLong();
public DefaultThreadPool() {
initializeWokers(DEFAULT_WORKER_NUMBERS);
}
public DefaultThreadPool(int num) {
workerNum = num > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS : num < MIN_WORKER_NUMBERS ? MIN_WORKER_NUMBERS : num;
initializeWokers(workerNum);
}
public void execute(HttpRequestHandler httpRequestHandler) {
if (httpRequestHandler != null) {
// 添加一个工作,然后进行通知
synchronized (jobs) {
jobs.addLast(httpRequestHandler);
jobs.notify();
}
}
}
public void shutdown() {
for (Worker worker : workers) {
worker.shutdown();
}
}
public void addWorkers(int num) {
synchronized (jobs) {
// 限制新增的Worker数量不能超过最大值
if (num + this.workerNum > MAX_WORKER_NUMBERS) {
num = MAX_WORKER_NUMBERS - this.workerNum;
}
initializeWokers(num);
this.workerNum += num;
}
}
public void removeWorker(int num) {
synchronized (jobs) {
if (num >= this.workerNum) {
throw new IllegalArgumentException("beyond workNum");
}
// 按照给定的数量停止Worker
int count = 0;
while (count < num) {
Worker worker = workers.get(count)
if (workers.remove(worker)) {
worker.shutdown();
count++;
}
}
this.workerNum -= count;
}
}
public int getJobSize() {
return jobs.size();
}
// 初始化线程工作者
private void initializeWokers(int num) {
for (int i = 0; i < num; i++) {
Worker worker = new Worker();
workers.add(worker);
Thread thread = new Thread(worker, "ThreadPool-Worker-" + threadNum.
incrementAndGet());
thread.start();
}
}
// 工作者,负责消费任务
class Worker implements Runnable {
// 是否工作
private volatile boolean running = true;
public void run() {
while (running) {
HttpRequestHandler job = null;
synchronized (jobs) {
// 如果工作者列表是空的,那么就wait
while (jobs.isEmpty()) {
try {
jobs.wait();
} catch (InterruptedException ex) {
// 感知到外部对WorkerThread的中断操作,返回
Thread.currentThread().interrupt();
return;
}
}
// 取出一个Job
job = jobs.removeFirst();
}
if (job != null) {
try {
job.run();
} catch (Exception ex) {
// 忽略Job执行中的Exception
}
}
}
}
public void shutdown() {
running = false;
}
}
}
package multiThread.art;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleHttpServer {
// 处理 HttpRequest 的线程池
static ThreadPool<HttpRequestHandler> threadPool = new DefaultThreadPool<HttpRequestHandler>(1);
// SimpleHttpServer 的根路径
static String basePath;
static ServerSocket serverSocket;
// 服务监听端口
static int port = 8080;
/**
* 设置 SimpleHttpServer 的服务端口
* @param port
*/
public static void setPort(int port){
if( port > 0){
SimpleHttpServer.port = port;
}
}
/**
* 设置 SimpleHttpServer 的根路径
* @param basePath
*/
public static void setBasePath(String basePath){
if( basePath != null && new File(basePath).exists() &&
new File(basePath).isDirectory() ){
SimpleHttpServer.basePath = basePath;
}
}
/**
* 启动 SimpleHttpServer
*/
public static void start() {
try {
serverSocket = new ServerSocket(port);
Socket socket = null;
while( (socket=serverSocket.accept()) != null){
/**
* 接收一个客户端 Socket ,生成一个 HttpRequestHandler ,放入线程池执行
*/
threadPool.execute( new HttpRequestHandler( socket, basePath));
}
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package multiThread.art;
import java.io.*;
import java.net.Socket;
public class HttpRequestHandler implements Runnable{
private Socket socket;
private String basePath;
public HttpRequestHandler(Socket socket,String basePath){
this.socket = socket;
this.basePath = basePath;
}
@Override
public void run() {
String line = null;
BufferedReader br = null ;
//缓冲字符输入流:BufferedReader
BufferedReader bufferedReader = null ;
// 字符输出流
PrintWriter printWriter = null ;
InputStream fileInputStream = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String header = bufferedReader.readLine();
// 由先对路径计算出绝对路径
String filePath = basePath + header.split(" ")[1];
printWriter = new PrintWriter(socket.getOutputStream());
// 如果请求资源的后缀为 jpg 或者 ico , 则读取资源并输出
if( filePath.endsWith("jpg") || filePath.endsWith("ico")){
fileInputStream = new FileInputStream(filePath);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i = 0;
while( (i = fileInputStream.read()) != -1){
byteArrayOutputStream.write(i);
}
byte[] bytes = byteArrayOutputStream.toByteArray();
// 打印到响应体的内容
printWriter.println("HTTP/1.1 200 OK");
printWriter.println("Server: Molly");
printWriter.println("Content-Type: image/jpeg");
printWriter.println("Content-Length: " + bytes.length);
printWriter.println("");
socket.getOutputStream().write(bytes,0,bytes.length);
}else{
br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println("HTTP/1.1 200 OK");
printWriter.println("Server: Molly");
printWriter.println("Content-Type: text/html; charset=UTF-8");
printWriter.println("");
while ((line = br.readLine()) != null) {
printWriter.println(line);
}
}
} catch (IOException e) {
printWriter.println("HTTP/1.1 500");
printWriter.println("");
// 刷新缓冲区 , 只针对“字符输出流”,对于在“字节”来说是空方法
printWriter.flush();
}finally {
close(fileInputStream,printWriter,bufferedReader,br,socket);
}
}
/**
* 关闭流或者 Socket
* Closeable : Closes this stream and releases any system resources associated with it
* @param closeables
*/
private static void close( Closeable... closeables){
if( closeables != null){
for( Closeable closeable : closeables){
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}