一个基于线程池技术的简单web 服务器---简单的demo

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();
                }
            }
        }
    }
}

 

如果你需要同时连接多个S7-1200并实现读写,可以使用线程池来实现。线程池是一组预先创建的线程,可以用于执行多个并发任务。以下是一个示例代码,可以使用线程池连接多个S7-1200并从它们读取数据: ```python import snap7 from concurrent.futures import ThreadPoolExecutor # 定义连接S7-1200的函数 def connect_plc(ip, port): plc = snap7.client.Client() plc.connect(ip, port) return plc # 定义读取S7-1200数据的函数 def read_data(plc): data = plc.read_area(snap7.types.Areas.DB, 1, 0, 10) return data # 定义S7-1200的IP地址和端口号 plc_ips = ['192.168.0.10', '192.168.0.20'] plc_ports = [102, 102] # 创建线程池,并连接到S7-1200 with ThreadPoolExecutor(max_workers=len(plc_ips)) as executor: plcs = list(executor.map(connect_plc, plc_ips, plc_ports)) # 读取S7-1200的数据 with ThreadPoolExecutor(max_workers=len(plcs)) as executor: data_list = list(executor.map(read_data, plcs)) # 输出读取的数据 for i, data in enumerate(data_list): print('Data from PLC', i+1, ':', data) # 关闭连接 for plc in plcs: plc.disconnect() ``` 在这个示例中,我们首先定义了两个S7-1200的IP地址和端口号,并将它们存储在plc_ips和plc_ports变量中。然后,我们使用线程池连接到这些S7-1200,并将连接的结果存储在plcs列表中。接下来,我们使用线程池从每个S7-1200的DB1区域读取了10个字节的数据,并将其存储在data_list列表中。最后,我们输出读取的数据并关闭连接。 值得注意的是,我们使用max_workers参数来设置线程池的最大工作线程数。在这个示例中,我们设置它为连接的S7-1200数量。这样可以确保我们的程序不会创建过多的线程,从而导致系统资源不足。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小达人Fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值