nodejs制作一个简单线程池

ThreadPool 类

const { Worker,parentPort,isMainThread } = require('worker_threads')
//主线程
if(isMainThread){
    class ThreadPool {
        size = 5;
        queue = [];
        workerGroup = [];
        free=0;
        maxFree=2;
        monitor=null;
        constructor(size) {
            this.size = size;
        }
        //初始化子线程
        init(){
            for (let i = 0; i < this.size; i++) {
                this.workerGroup.push({
                    id: i,
                    status: false,
                    worker: new Worker(__filename)
                });
                this.workerGroup[i].worker.on("message", (message) => {
                    if (message === 'end') {
                        this.workerGroup[i].status = false;
                        this.check();
                    }
                });
            }
            this.monitor=setInterval(()=>{
                if(this.isFree()){
                    this.free++;
                    console.log(`空闲次数: ${this.free},如果超过${this.maxFree}次,线程池将关闭,后续提交任务将自动开启`)
                }else{
                    this.free=0;
                }
                this.check();
                if(this.free>this.maxFree){
                    this.shutdown();
                    clearInterval(this.monitor);
                    this.monitor=null;
                    this.workerGroup = [];
                    this.free=0;
                }
            },10000)
        }
        isFree(){
            for (let i = 0; i < this.workerGroup.length; i++) {
                if (this.workerGroup[i].status) {
                    return false;
                }
            }
            if(this.queue.length>0){
                return false;
            }
            return true;
        }
    
        //清理所有子线程
        shutdown() {
            this.workerGroup.forEach(e => {
                e.worker.terminate();
            });
        }

        /**
         * 提交异步任务
         * @param {*} taskContext  任务函数
         * @param {*} data 任务所需参数
         */
        submitAsync(taskContext,data) {
            this.add(true,taskContext,data)
        }

        /**
         * 提交同步任务
         * @param {*} taskContext  任务函数
         * @param {*} data 任务所需参数
         */
        submit(taskContext,data) {
            this.add(false,taskContext,data)
        }

        //添加任务排队
        add(isAsync,taskContext,data){
            if(this.workerGroup.length<1)this.init();//懒加载
            this.queue.push({
                isAsync:isAsync,
                data:data,
                taskContext:taskContext.toString()
            });
            this.check();
        }
        //检查任务
        check() {
            if(this.queue.length>0){
                for (let i = 0; i < this.workerGroup.length; i++) {
                    if (!this.workerGroup[i].status) {
                        this.workerGroup[i].status = true;
                        this.workerGroup[i].worker.postMessage(this.queue.pop());
                        break;
                    }
                }
            }
        }
    }
    module.exports = ThreadPool;
}else{//子线程
    //监听任务
    parentPort.on("message", (task) => {
        if(task.isAsync){
            let taskContext=eval("("+task.taskContext+")")
            taskContext(()=>{
                parentPort.postMessage('end')//通知主线程任务结束
            },task.data);
        }else{
            let taskContext=eval("("+task.taskContext+")")
            taskContext(task.data);
            parentPort.postMessage('end')//通知主线程任务结束
        }
    })
}


使用方式


const ThreadPool = require('./ThreadPool');
const pool = new ThreadPool(2);

let data = { name: '你好' }

// 异步任务
pool.submitAsync(end => {
      setTimeout(() => {
            console.log("任务一开始" + new Date().getTime());
            let num = 0;
            while (true) {
                  num++;
                  if (num > 100000000) {
                        console.log("任务一结束" + new Date().getTime());
                        break;
                  }
            }
            end();
      }, 1000);
});

//异步任务+入参
pool.submitAsync((end, data1) => {
      setTimeout(() => {
            let num = 0;
            console.log("任务二开始" + new Date().getTime() + ",data=" + JSON.stringify(data1));
            while (true) {
                  num++;
                  if (num > 100000000) {
                        console.log("任务二结束" + new Date().getTime());
                        break;
                  }
            }
            end();
      }, 1000);
}, data);

//同步任务
pool.submit(data1 => {

      console.log("任务一开始" + new Date().getTime() + ",data" + JSON.stringify(data1));
      let num = 0;
      while (true) {
            num++;
            if (num > 100000000) {
                  console.log("任务一结束" + new Date().getTime());
                  break;
            }
      }

}, data);

//同步任务+入参
pool.submit(data1 => {
      console.log("任务二开始" + new Date().getTime() + ",data" + JSON.stringify(data1));
      let num = 0;
      while (true) {
            num++;
            if (num > 100000000) {
                  console.log("任务二结束" + new Date().getTime());
                  break;
            }
      }
}, data);

输出日志

任务一开始1706802924114
任务二开始1706802924114,data={"name":"你好"}
任务二结束1706802924196
任务一结束1706802924197
任务二开始1706802924197,data{"name":"你好"}
任务二结束1706802924271
任务一开始1706802924197,data{"name":"你好"}
任务一结束1706802924272
空闲次数: 1,如果超过2次,线程池将关闭,后续提交任务将自动开启
空闲次数: 2,如果超过2次,线程池将关闭,后续提交任务将自动开启
空闲次数: 3,如果超过2次,线程池将关闭,后续提交任务将自动开启

如果是简单的setTimeout,输出日志就是顺序执行的,非并发。

你可能感兴趣的:(js,前端,node.js,服务器)