我对网络工作者和多线程设计都很陌生,我需要设计的是一个简单的查询任务调度程序(现在使用web worker),如:
var taskScheduler = {};
taskScheduler.pool = [];
function init(num){
for(var i=0; i<num; i++){
var workUnit = {};
var worker = new Worker("worker.js");
workUnit.busy = false;
workUnit.worker = worker;
taskScheduler.pool.push( workUnit );
}
}
init(4);
下面的代码应该是循环查询workUnit availability并开始新的工作 我不太确定如何实现,我认为应该是这样的:
taskScheduler.startWork = function(task){
for(var i=0; i<taskScheduler.pool.length; i++){
if(!taskScheduler.pool.busy){ // fire job, make unit busy then break; }
}
}
目前主要的挑战是:
如何在仍然能够接受新任务调用的同时继续检查工作人员的可用性(例如:如果没有可用的工作人员,它将继续询问哪个将阻止接受taskScheduler.startWork的新作业调用的能力)< / p>
答案 0 :(得分:0)
这样做的一种方法是在所有工人忙碌后延迟致电startWork
taskScheduler.startWork = function(task){
for(var i=0; i<taskScheduler.pool.length; i++){
if(!taskScheduler.pool.busy) {
// fire job, make unit busy then return;
}
}
setTimeout(function() {
taskScheduler.startWork(task);
}, 500);
}
这种方式有问题
但是
更好的选择是在主线程中实现任务队列。我将此留给另一个答案: - )
答案 1 :(得分:0)
这样做的一种方法是实现任务队列。其中
尝试在2种情况下处理队列中最旧的项目
下面是一个简单的部分实现
taskScheduler.queue = [];
taskScheduler.addToQueue(task) {
queue.push(task);
taskScheduler.processQueue();
}
taskScheduler.processQueue() {
if (!queue.length) return;
var task = queue.shift();
for (var i=0; i<taskScheduler.pool.length; i++) {
if (!taskScheduler.pool.busy) {
// fire job, make unit busy then break
}
}
}
function init(num) {
...
worker.onmessage = function(e) {
// Assuming a worker is finished if it passes a message back to main thread
workUnit.busy = false;
processQueue();
}
...
}
这样
保证以添加到队列的顺序启动任务
当等待任务时,工人花很少的时间不做任何事情
如果需要,您可以添加逻辑来控制队列。即清除未启动的任务,重新安排订单等。
但是
答案 2 :(得分:0)
如果您知道每项任务将花费大约相同的时间,具体取决于您的使用情况,您可以放弃任何类型的忙碌&#34;状态,并依次向工人发射任务。每条消息都将按Javascript排队,直到每个工作程序中的堆栈都已清除
taskScheduler.nextWorkerIndex = 0;
taskScheduler.startWork = function(task){
var worker = taskScheduler.pool[taskScheduler.nextWorkerIndex];
taskScheduler.nextWorkerIndex = (taskScheduler.nextWorkerIndex + 1) % taskScheduler.pool.length
// Fire job
}
这有
但
如果任务花费相同的时间,那么任务可能已经发送给忙碌的工作人员,而其他人则是免费的
很难管理任务队列,因为一旦发送了一条消息,直到工作人员收到该消息,它就会被Javascript代码隐藏起来。
答案 3 :(得分:0)
从一开始就检查工人的可用性是错误的概念。 Javascript是事件驱动语言。您不会轮询更改,而是使用事件监听它们。
您应该做的是以下内容:
var tasksToProcess = [/*{task: this is sent to worker, onfinish: onfinish callback}*/];
var processedTask = null;
var worker = new Worker("taskProcessor.js");
// The worker dispatches a message when task is completed
worker.addEventListener("message", function(event) {
//Usually I give messages names to simulate Javascript event style
if(event.data.name == "task_success") {
if(processedTask!=null) {
if(processedTask.onfinish instanceof Function)
// If onfinish throws error, it will not crash this function
setTimeout(processedTask.onfinish,0);
processedTask = null;
}
else
console.error("Weird, task sucessfully completed when no task was running.");
// No matter what, try to start next task
runNextTask();
}
});
function runNextTask() {
// Only run when no task is being processed
if(processedTask==null && tasksToProcess.length>0) {
//Shift removes and returns first value of array
processedTask = tasksToProcess.shift();
worker.postMessage({name:"task", task: processedTask.task});
}
}
/// Task in format {task: task data, onfinish: finish event callback}
function addTask(task) {
// Add task to the end
tasksToProcess.push(task);
runNextTask();
}
只要工作人员在完成任务后正确调用消息,这将起作用。你也应该实现Worker onerror回调,以便你可以从错误中恢复。