Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS实现一个带并发限制的异步调度器Scheduler #2

Open
Yuanyuanyuanc opened this issue Aug 1, 2019 · 8 comments
Open

JS实现一个带并发限制的异步调度器Scheduler #2

Yuanyuanyuanc opened this issue Aug 1, 2019 · 8 comments

Comments

@Yuanyuanyuanc
Copy link
Owner

// JS实现一个带并发限制的异步调度器Scheduler,
// 保证同时运行的任务最多有两个。
// 完善代码中Scheduler类,
// 使得以下程序能正确输出

class Scheduler {
	constructor() {
		this.count = 2
		this.queue = []
		this.run = []
	}

	add(task) {
                 // ...
	}
}


const timeout = (time) => new Promise(resolve => {
	setTimeout(resolve, time)
})

const scheduler = new Scheduler()
const addTask = (time, order) => {
	scheduler.add(() => timeout(time)).then(() => console.log(order))
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// output: 2 3 1 4

// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
@Yuanyuanyuanc
Copy link
Owner Author

class Scheduler {
	constructor(count) {
		this.count = 2
		this.queue = []
		this.run = []
	}

	add(task) {
		this.queue.push(task)
		return this.schedule()
	}

	schedule() {
		if (this.run.length < this.count && this.queue.length) {
		  	const task = this.queue.shift()
		  	const promise = task().then(() => {
		  		this.run.splice(this.run.indexOf(promise), 1)
		  	})
		  	this.run.push(promise)
		  	return promise
		} else {
		  	return Promise.race(this.run).then(() => this.schedule())
		}
	}
}

@licong-site
Copy link

class Scheduler{
  constructor(limit = 2){
    this.limit = limit;
    this.queue = [];  // 模拟队列,先进先出
    this.processTasks = [];
  }
  addTask(...fns){
    this.queue.push(...fns);
    this.run();
  }
  run(){
    while(this.processTasks.length < this.limit && this.queue.length > 0){
      let task = this.queue.shift();
      let promise = task().then(() => {
        this.processTasks.splice(this.processTasks.indexOf(promise), 1);
        this.run();
      });
      this.processTasks.push(promise);
    }
  }
}

var task = function(time, order){
    var fn = function(){
        console.log('开始执行',order)
        return new Promise(resolve => {
	       setTimeout(resolve, time)
        }).then(() => console.log('执行完成',order))
    }
    return fn;
}

var scheduler = new Scheduler(2);
scheduler.addTask(task(4000, '1'));
scheduler.addTask(task(500, '2'));
scheduler.addTask(task(500, '3'));
scheduler.addTask(task(400, '4'));
scheduler.addTask(task(300, '5'));
scheduler.addTask(task(300, '6')); 

@Aggie123
Copy link

`
class Scheduler{
constructor(limit){
this.limit=limit;
}
list=[]
count=0

    async add(fn){
        if(this.count>=this.limit){
            await new Promise(resolve=>this.list.push(resolve));
        }
        this.count++;
        let res=await fn();
        this.count--;

        if(this.list.length>0){
            this.list.shift()();
        }
        return res;

    }
}

let schedule =new Scheduler(2);

function asyncFactory(n,time){
    return function(){
        return new Promise(resolve=>{
            setTimeout(()=>resolve(n),time);
        })
    }
}

schedule.add(asyncFactory(1, 1000)).then((n) => { console.log(`异步任务:${n}`) });
schedule.add(asyncFactory(2, 500)).then((n) => { console.log(`异步任务:${n}`) });
schedule.add(asyncFactory(3, 300)).then((n) => { console.log(`异步任务:${n}`) });
schedule.add(asyncFactory(4, 400)).then((n) => { console.log(`异步任务:${n}`) });
schedule.add(asyncFactory(5, 200)).then((n) => { console.log(`异步任务:${n}`) });
schedule.add(asyncFactory(6, 2000)).then((n) => { console.log(`异步任务:${n}`) });
//2,3,1,5,4,6

`

@stackOverflowHidden
Copy link

class Scheduler {
constructor() {
this.count = 2
this.queue = []
this.run = []
}

// const task = () => timeout(time);
add(task) {
    const tmp = new Promise((resolve, reject) => {
        if (this.run.length === this.count) {
            this.queue.push({
                resolve: resolve,
                task: task
            });
        }
        else {
            this.run.push(resolve);
            task().then(() => {
                resolve(resolve);
            })
        }
    })
        .then((resolve) => {
            const index = this.run.findIndex(item => item === resolve);
            this.run.splice(index, 1);

            if (this.queue.length > 0) {
                const haha = this.queue.shift();
                this.run.push(haha.resolve);
                haha.task().then(() => {
                    haha.resolve(haha.resolve);
                })
            }

            return;
        });

    return tmp;
}

}

@PstereoJW
Copy link

PstereoJW commented Dec 21, 2022

ChatGPT的答案如下,能通过测试用例,个人感觉这种写法在理解上会简单一点:

class Scheduler {
  constructor() {
    this.count = 2;
    this.queue = [];
    this.run = [];
  }

  add(task) {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, resolve, reject });
      if (this.run.length < this.count) {
        this._runTask();
      }
    });
  }

  _runTask() {
    const { task, resolve, reject } = this.queue.shift();
    this.run.push(task);
    task().then(
      (result) => {
        this.run.splice(this.run.indexOf(task), 1);
        resolve(result);
        if (this.queue.length > 0) {
          this._runTask();
        }
      },
      (error) => {
        this.run.splice(this.run.indexOf(task), 1);
        reject(error);
        if (this.queue.length > 0) {
          this._runTask();
        }
      }
    );
  }
}

@asmallkite
Copy link

class Scheduler {

    constructor(max) {
        this.max = max;
        this.array = [];
        this.count = 0;
    }
  
    async add(fn) {
        if (this.count >= this.max) {
            await new Promise((resolve, reject) => {
                this.array.push(resolve);
            })
        }

        this.count++;
        const res = await fn();
        this.count--;
        if (this.array.length > 0) {
            this.array.unshift()();
        }
        return res;
    }
}

@whale2002
Copy link

// JS实现一个带并发限制的异步调度器Scheduler,
// 保证同时运行的任务最多有两个。
// 完善代码中Scheduler类,
// 使得以下程序能正确输出

class Scheduler {
	constructor() {
		this.count = 2
		this.queue = []
		this.runCount = 0

    setTimeout(() => {
      this.start()
    })
	}

  add(task) {
    this.queue.push(task)
  }
  
  start() {
    for (let i = 0; i < this.count; i++) {
      this.run()
    }
  }

  run() {
    if (!this.queue.length || this.runCount > this.count) return
    
    this.runCount++

    const task = this.queue.shift()
    task().then(() => {
      this.runCount--
      this.run()
    })
  }
}


const timeout = (time) => new Promise(resolve => {
	setTimeout(resolve, time)
})

const scheduler = new Scheduler()
const addTask = (time, order) => {
	scheduler.add(() => timeout(time).then(() => console.log(order)))
}

const startTime = new Date()
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// output: 2 3 1 4

// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4

@Geranium-boop
Copy link

class Scheduler {

    constructor(max) {
        this.max = max;
        this.array = [];
        this.count = 0;
    }
  
    async add(fn) {
        if (this.count >= this.max) {
            await new Promise((resolve, reject) => {
                this.array.push(resolve);
            })
        }

        this.count++;
        const res = await fn();
        this.count--;
        if (this.array.length > 0) {
            this.array.unshift()();
        }
        return res;
    }
}

这里应该是shift()()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants