Java 简单的HTTP服务器使CPU保持满负荷,尽管TaskManager和Netbeans另有说明

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% 这是服务器本

出于无聊,我制作了一个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实例;
私有静态执行器服务执行器;
私有静态数组列表