js线程池开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>线程池</title>
</head>
<body>
<button id="addTask">加入任务</button>
<textarea id="task" placeholder="任务记录"></textarea>
<script src="main.js"></script>
<script>
document.getElementById('addTask').addEventListener('click', () => {
for (let i = 0; i < 3; i++) {
pool.submitTask(`Task ${i}`).then((result) => {
console.log(result);
});
}
});
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
class WorkerPool {

static instance;
// 构造函数
constructor(maxWorkers, workerScript) {
if (WorkerPool.instance) {
return WorkerPool.instance;
}

console.log('创建线程池');
document.getElementById('task').value += `创建线程池\n`;


this.maxWorkers = maxWorkers; // 最大线程数
this.workerScript = workerScript; // Worker 的脚本内容
this.workers = []; // 存储 Worker 实例
this.taskQueue = []; // 任务队列
this.idleWorkers = []; // 空闲线程数组

// 初始化线程池
this.initialize();

WorkerPool.instance = this;
}

// 初始化线程池,创建最大数量的 Worker
initialize() {
for (let i = 0; i < this.maxWorkers; i++) {
const worker = new Worker(this.workerScript);
worker.onmessage = (event) => this.handleTaskComplete(worker, event);
worker.onerror = (error) => console.error('Worker error:', error);
this.workers.push(worker);
this.idleWorkers.push(worker);
}
}

// 处理任务完成
handleTaskComplete(worker, event) {
console.log('Task completed:', event.data);
document.getElementById('task').value += event.data + '\n';

// 将 Worker 放回空闲线程数组
this.idleWorkers.push(worker);

// 如果任务队列中还有任务,分配给空闲线程
if (this.taskQueue.length > 0) {
const {
task,
resolve,
reject
} = this.taskQueue.shift();
this.runTask(task, resolve, reject);
}
}

// 提交任务
submitTask(task) {
return new Promise((resolve, reject) => {
// 如果有空闲线程,直接运行任务
if (this.idleWorkers.length > 0) {
this.runTask(task, resolve, reject);
} else {
// 否则将任务加入队列
this.taskQueue.push({
task,
resolve,
reject
});
}
});
}

// 分配任务给线程
runTask(task, resolve, reject) {
if (this.idleWorkers.length > 0) {
const worker = this.idleWorkers.pop();
try {
worker.postMessage(task); // 将任务发送到 Worker
worker._resolve = resolve; // 保存 Promise 的 resolve,用于回调
worker._reject = reject;
} catch (error) {
reject(error);
this.idleWorkers.push(worker); // 如果出错,将线程放回空闲池
}
}
}

// 销毁所有线程
terminate() {
this.workers.forEach((worker) => worker.terminate());
this.workers = [];
this.idleWorkers = [];
this.taskQueue = [];
}
}


// 示例 Worker 脚本代码
const workerScript = `
self.onmessage = (event) => {
const task = event.data;

console.log('Processing:', task);

// 模拟耗时任务
setTimeout(() => {
const result = \`Processed: \${task}\`;
self.postMessage(result);
}, Math.random() * 2000 + 1000);
};
`;

// 将 Worker 脚本动态转为 Blob URL
const blob = new Blob([workerScript], {
type: 'application/javascript'
});
const workerScriptUrl = URL.createObjectURL(blob);

// 初始化线程池,最大线程数为 6
const pool = new WorkerPool(6, workerScriptUrl);


// 提交任务
for (let i = 0; i < 10; i++) {
pool.submitTask(`Task ${i}`);
}

// 页面关闭时销毁线程池
window.addEventListener('beforeunload', () => {
pool.terminate();
});