线程池改造
上一篇文章中我们用了Excutors创建了线程,这里我们将它改造成包含所有线程池核心参数的形式。
package com.tomcatServer.http;
import java.util.concurrent.*;
/**
* 线程池跑龙套
*
* @author ez4sterben
* @date 2023/08/05
*/
public class ThreadPool {
private int corePoolSize;
private int maximumPoolSize;
private long keepAliveTime;
private static ThreadPoolExecutor threadPoolExecutor;
public ThreadPool() {
}
public synchronized ThreadPoolExecutor getInstance() {
if (threadPoolExecutor == null) {
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
threadFactory
);
}
return threadPoolExecutor;
}
public static synchronized void shutdown() {
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdown();
threadPoolExecutor = null;
}
}
public int getCorePoolSize() {
return corePoolSize;
}
public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}
public void setMaximumPoolSize(int maximumPoolSize) {
this.maximumPoolSize = maximumPoolSize;
}
public void setKeepAliveTime(long keepAliveTime) {
this.keepAliveTime = keepAliveTime;
}
}
主方法中对多线程操作部分改为使用CompletableFuture执行
// 5.初始化线程池
ThreadPoolExecutor executor = XmlParseUtil.initThreadPool(ROOT);
// 6.处理http请求
try {
SocketStore.connect(port);
while (true){
Socket accept = SocketStore.getSocket().accept();
if (accept != null){
CompletableFuture.runAsync(() -> {
try {
SocketStore.handleRequest(accept);
} catch (IOException e) {
throw new RuntimeException(e);
}
}, executor);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
SocketStore.close();
}
解析xml文件
现在我们有一个server.xml文件,我想解析其中的端口号以及线程池参数
<tomcat-server>
<port>80</port>
<core-pool-size>4</core-pool-size>
<maximum-pool-size>8</maximum-pool-size>
<keep-alive-time>60</keep-alive-time>
</tomcat-server>
如果想完成这个功能可以直接使用java本身自带的工具类,下面附上代码
package com.tomcatServer.utils;
import com.tomcatServer.http.ThreadPool;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadPoolExecutor;
public class XmlParseUtil {
public static Integer parseServerConfig(String root){
int port = 8080;
try {
NodeList nodeList = getServerConfig(root);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
port = Integer.parseInt(element.getElementsByTagName("port").item(0).getTextContent().trim());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return port;
}
public static ThreadPoolExecutor initThreadPool(String root){
ThreadPool threadPool = new ThreadPool();
int corePoolSize = 4;
int maximumPoolSize = 8;
int keepAliveTime = 60;
try {
NodeList nodeList = getServerConfig(root);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
corePoolSize = Integer.parseInt(element.getElementsByTagName("core-pool-size").item(0).getTextContent().trim());
maximumPoolSize = Integer.parseInt(element.getElementsByTagName("maximum-pool-size").item(0).getTextContent().trim());
keepAliveTime = Integer.parseInt(element.getElementsByTagName("keep-alive-time").item(0).getTextContent().trim());
}
}
} catch (Exception e) {
e.printStackTrace();
}
threadPool.setCorePoolSize(corePoolSize);
threadPool.setMaximumPoolSize(maximumPoolSize);
threadPool.setKeepAliveTime(keepAliveTime);
System.out.println(threadPool.getCorePoolSize());
return threadPool.getInstance();
}
private static NodeList getServerConfig(String root) throws ParserConfigurationException, SAXException, IOException {
File inputFile = new File(root + "\\src\\main\\java\\com\\tomcatServer\\config\\server.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inputFile);
document.getDocumentElement().normalize();
return document.getElementsByTagName("tomcat-server");
}
}
启动测试
现在我的配置文件是这样的,在主方法中打印一下端口号,如果是80说明这个xml扫描成功了,然后我们再去访问80端口的Index页面。
http://localhost:8080/index.html
尝试访问8080时,已经无法访问了
接下来访问80端口
访问成功
现在我们的tomcat已经有一定的功能了,下一篇作者将对整个tomcat的代码结构做一些优化,并将现阶段的代码分享给读者。
【仿写tomcat】七、项目结构优化以及代码开源