[size=medium][b]为什么使用线程池?[/b][/size]
[size=medium]为了减少瞬间峰值问题,服务器一般都使用线程池,规定了同时并发的最大数量,避免了线程的无限增长.[/size]
在浏览器里输出 http://127.0.0.1:8888/
就可以出结果了
[size=medium]Main.java[/size]
[size=medium]EchoServer.java[/size]
[size=medium]ThreadPool.java[/size]
[size=medium]Handler.java[/size]
[size=medium]为了减少瞬间峰值问题,服务器一般都使用线程池,规定了同时并发的最大数量,避免了线程的无限增长.[/size]
在浏览器里输出 http://127.0.0.1:8888/
就可以出结果了
[size=medium]Main.java[/size]
package com.apq.threadpool;
import com.apq.server.MiniServer;
public class Main {
public static void main(String[] args) {
new EchoServer(8888, 1000).service();
}
}
[size=medium]EchoServer.java[/size]
package com.apq.threadpool;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EchoServer {
//监听的端口号
private final int port;
//单个cpu工作线程数量
private final int poolSize;
private ServerSocket serverSocket;
//线程池
private ThreadPool threadPool;
//jdk线程池
private ExecutorService executorService;
public EchoServer(int port, int poolSize) {
this.port = port;
this.poolSize = poolSize;
//this.threadPool = new ThreadPool(Runtime.getRuntime().availableProcessors() * poolSize);
this.executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * poolSize);
}
//负责为每个客户分配一个线程
public void service() {
try {
serverSocket = new ServerSocket(port);
echo("Listening on " + serverSocket);
while(true) {
echo("Accepting...");
Socket clientSocket = serverSocket.accept();
echo("Connected to " + clientSocket);
//创建一个工作线程并启动(没有线程池的)
//new Thread(new Handler(clientSocket)).start();
//由线程池来处理客户通信
//this.threadPool.putHandler(new Handler(clientSocket));
//用jdk自带的线程池来处理客户通信
this.executorService.execute(new Handler(clientSocket));
}
} catch (IOException e) {
System.err.println(e);
}
}
private void echo(String msg) {
System.out.println(msg);
}
}
[size=medium]ThreadPool.java[/size]
package com.apq.threadpool;
import java.util.*;
public class ThreadPool extends ThreadGroup {
private static final int MAX_HANDLER = 100;
// 线程数量
private int poolSize;
// 工作队列
private static LinkedList<Runnable> workQueue;
// 线程池ID
private static int threadPoolID;
// 工作线程ID
private int workThreadPoolID;
private int count;
// 构造函数
public ThreadPool(int poolSize) {
super("ThreadPool-" + (threadPoolID++));
this.poolSize = poolSize;
this.count = 0;
workQueue = new LinkedList<Runnable>();
startWorks();
System.out.println("The EchoServer has started.");
}
// 创建并启动工作线程
private void startWorks() {
for (int i = 0; i < this.poolSize; i++) {
new WorkThread().start();
}
}
// 向工作队列加入一个新任务,由工作线程执行该任务
public synchronized void putHandler(Runnable handler) {
while (count >= MAX_HANDLER) {
try {
wait();
} catch (InterruptedException e) {
}
}
workQueue.add(handler);
count++;
notifyAll();
}
// 从工作队列中取出一个任务,工作线程会调用此方法
public synchronized Runnable getHandler() {
while (count <= 0) {
try {
wait();
} catch (InterruptedException e) {
}
}
Runnable handler = workQueue.removeFirst();
count--;
notifyAll();
return handler;
}
// 内部类 工作线程
private class WorkThread extends Thread {
public WorkThread() {
}
@Override
public void run() {
while (!isInterrupted()) {
Runnable handler = getHandler();
if (handler != null)
handler.run();
}
}
}
}
[size=medium]Handler.java[/size]
package com.apq.threadpool;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
//负责与单个客户的通信
public class Handler implements Runnable {
private Socket clientSocket;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
DataOutputStream out = new DataOutputStream(clientSocket
.getOutputStream());
out.writeBytes("HTTP/1.1 200 OK\r\n");
out.writeBytes("Content-type: text/html\r\n");
out.writeBytes("\r\n");
out.writeBytes("<html><head></head><body>");
out.writeBytes("<p>" + "new connection accepted!<br>"
+ clientSocket.getInetAddress() + ":"
+ clientSocket.getPort() + "</p>");
out.writeBytes("</body></html>");
} catch (IOException e) {
//record log
} finally {
if (clientSocket != null)
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}