Java 简单的HTTP服务器使CPU保持满负荷,尽管TaskManager和Netbeans另有说明
出于无聊,我制作了一个HTTP服务器,并制作了一个单文件程序。 问题是,当为一个大文件(例如1.2GB)提供服务时,CPU会一直上升到100%,而我的Lenovo X220会立即跳到80C 问题是Netbeans概要文件和任务管理器都报告它使用了那么多CPU。让我们来看一看: 这里是服务大文件,这是按CPU排序的任务管理器,显示所有进程: 没什么可疑的,但是在性能标签中,所有的地狱都被打破了: 在全涡轮增压(3.2GHz)下,我的i5 2520m将所有四个核心锁定到几乎99% 这是服务器本身,只需将其复制到名为Java 简单的HTTP服务器使CPU保持满负荷,尽管TaskManager和Netbeans另有说明,java,netbeans,profiling,Java,Netbeans,Profiling,出于无聊,我制作了一个HTTP服务器,并制作了一个单文件程序。 问题是,当为一个大文件(例如1.2GB)提供服务时,CPU会一直上升到100%,而我的Lenovo X220会立即跳到80C 问题是Netbeans概要文件和任务管理器都报告它使用了那么多CPU。让我们来看一看: 这里是服务大文件,这是按CPU排序的任务管理器,显示所有进程: 没什么可疑的,但是在性能标签中,所有的地狱都被打破了: 在全涡轮增压(3.2GHz)下,我的i5 2520m将所有四个核心锁定到几乎99% 这是服务器本
JavaApplication1.java的文件中即可
这是怎么回事
package javaapplication1;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class JavaApplication1 {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(80);
ServiceManager manager = ServiceManager.getManager();
while (true) {
Socket sock = server.accept();
HttpResponse response = new HttpResponse(sock);
manager.submit(response);
}
}
}
class ServiceManager {
private static ServiceManager instance;
private static ExecutorService executor;
private static ArrayList<Future<?>> taskPool;
private static final int MAX_WORKERS = 150;
private ServiceManager() {
executor = Executors.newFixedThreadPool(MAX_WORKERS);
taskPool = new ArrayList<>();
}
public static ServiceManager getManager() {
if (instance == null) {
instance = new ServiceManager();
}
return instance;
}
public void registerService(Runnable runnable) {
taskPool.add(executor.submit(runnable));
}
void submit(HttpResponse response) {
executor.submit(response);
}
}
class HttpAccept {
private final ByteArrayOutputStream baos;
private final InputStream in;
private final Callback<HttpAccept> back;
public HttpAccept(InputStream in, Callback<HttpAccept> back) {
baos = new ByteArrayOutputStream(512);
this.in = in;
this.back = back;
}
public void readAndRespond() {
byte[] buf = new byte[512];
int b;
try {
while ((b = in.read(buf)) > 0) {
baos.write(buf, 0, b);
if (HttpTools.endsWithCrlfCrlf(baos.toByteArray())) {
back.callback(this);
return;
}
}
} catch (IOException ex) {
System.err.println(ex);
}
}
public void call(Callback<HttpAccept> back) {
back.callback(this);
}
public String getHttpHeader() {
return new String(baos.toByteArray(), StandardCharsets.UTF_8);
}
}
interface Callback<E> {
void callback(E a);
}
class HttpHeader {
private final ByteArrayOutputStream baos;
private final String raw;
public HttpHeader(String raw) {
baos = new ByteArrayOutputStream(512);
this.raw = raw;
}
public String getRequestPath() {
char[] workset = raw.toCharArray();
for (char c : workset) {
baos.write((byte) c);
if (HttpTools.endsWithCrlf(baos.toByteArray())) {
String response[] = baos.toString().split(" ");
if (response.length == 0) return "./error.html";
if (response[1].equals("/")) return "./index.html";
return ".".concat(response[1]);
}
}
return "./";
}
}
abstract class HttpTools {
private static final byte[] CRLFCRLF = {13, 10, 13, 10};
private static final byte[] CRLF = {13, 10};
public static boolean endsWithCrlfCrlf(byte[] arr) {
if (arr.length < 4) {
return false;
}
int len = arr.length - 1;
return (arr[len] == CRLFCRLF[3]
&& arr[len - 1] == CRLFCRLF[2]
&& arr[len - 2] == CRLFCRLF[1]
&& arr[len - 3] == CRLFCRLF[0]);
}
public static boolean endsWithCrlf(byte[] arr) {
if (arr.length < 2) {
return false;
}
int len = arr.length - 1;
return (arr[len] == CRLF[1]
&& arr[len - 1] == CRLF[0]);
}
}
class HttpResponse implements Runnable {
private final Socket conn;
public HttpResponse(Socket conn) {
this.conn = conn;
}
public void respond() throws IOException {
HttpAccept accept = new HttpAccept(conn.getInputStream(), (httpAcc) -> {
try (OutputStream out = conn.getOutputStream()) {
HttpHeader header = new HttpHeader(httpAcc.getHttpHeader());
String path = header.getRequestPath();
File file = new File(path);
if (file.exists()) {
writeResponse(out, 200);
FileInputStream in = new FileInputStream(file);
byte[] buf = new byte[4096];
int b;
while ((b = in.read(buf)) > 0) {
out.write(buf, 0, b);
}
} else {
writeResponse(out, 404);
}
writeEnd(out);
} catch (IOException e) {
System.err.println(e);
}
});
accept.readAndRespond();
}
@Override
public void run() {
try {
respond();
} catch (IOException ex) {
System.err.println(ex);
}
}
private void writeResponse(OutputStream out, int i) throws IOException {
char[] resp = String.format("HTTP/1.1 %s OK\r\n\r\n", i).toCharArray();
for (char c : resp) {
out.write((int) c);
}
if (i == 404) {
char[] four0four = "<b>404 - Not found</b>".toCharArray();
for (char c : four0four) {
out.write((int) c);
}
}
}
private void writeEnd(OutputStream out) throws IOException {
char[] resp = "\r\n\r\n".toCharArray();
for (char c : resp) {
out.write((int) c);
}
}
}
PackageJavaApplication1;
导入java.io.ByteArrayOutputStream;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.net.ServerSocket;
导入java.net.Socket;
导入java.nio.charset.StandardCharset;
导入java.util.ArrayList;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
公共类JavaApplication1{
公共静态void main(字符串[]args)引发异常{
ServerSocket服务器=新的ServerSocket(80);
ServiceManager=ServiceManager.getManager();
while(true){
Socket sock=server.accept();
HttpResponse响应=新的HttpResponse(sock);
经理。提交(回复);
}
}
}
类服务管理器{
私有静态ServiceManager实例;
私有静态执行器服务执行器;
私有静态数组列表