├── .gitignore ├── eslint.config.js ├── prettier.config.js ├── README.md ├── JavaScript ├── 4-access.js ├── 5-access.js ├── 2-worker.js ├── 4-share.js ├── 3-server.js ├── 5-share.js ├── 2-master.js ├── 3-http.js └── 1-worker.js ├── .editorconfig ├── package.json └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const init = require('eslint-config-metarhia'); 4 | 5 | init[0].ignores.push('JavaScript/6-horror.js'); 6 | 7 | module.exports = init; 8 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | printWidth: 80, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | tabWidth: 2, 8 | useTabs: false, 9 | semi: true, 10 | }; 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Multithreading: WorkerThreads, Workers, SharedWorkers 2 | 3 | [![Atomics, SharedArrayBuffer, worker_threads в Node.js](https://img.youtube.com/vi/zLm8pnbxSII/0.jpg)](https://www.youtube.com/watch?v=zLm8pnbxSII) 4 | -------------------------------------------------------------------------------- /JavaScript/4-access.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | 5 | const { buffer } = threads.workerData; 6 | const array = new Int8Array(buffer); 7 | array[0] = 123; 8 | threads.parentPort.postMessage({ name: 'display' }); 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | charset = utf-8 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [{*.js,*.mjs,*.ts,*.json,*.yml}] 11 | indent_size = 2 12 | indent_style = space 13 | -------------------------------------------------------------------------------- /JavaScript/5-access.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | 5 | const { buffer } = threads.workerData; 6 | const array = new Int8Array(buffer); 7 | 8 | setInterval(() => { 9 | for (let j = 0; j < 1024; j++) { 10 | array[j] += 1; 11 | } 12 | }, 100); 13 | -------------------------------------------------------------------------------- /JavaScript/2-worker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | 5 | console.dir({ worker: threads }); 6 | threads.parentPort.postMessage('Message from Worker to Master'); 7 | threads.parentPort.on('message', (data) => { 8 | console.dir({ data }); 9 | }); 10 | 11 | process.exit(0); 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "patterns", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "lint": "eslint . && prettier -c \"**/*.js\"", 6 | "fix": "eslint . --fix && prettier --write \"**/*.js\"" 7 | }, 8 | "author": "Timur Shemsedinov", 9 | "private": true, 10 | "dependencies": { 11 | "eslint": "^9.12.0", 12 | "eslint-config-metarhia": "^9.1.0", 13 | "prettier": "^3.3.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /JavaScript/4-share.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | const { Worker } = threads; 5 | 6 | const buffer = new SharedArrayBuffer(1024); 7 | const array = new Int8Array(buffer); 8 | 9 | const worker = new Worker('./4-access.js', { workerData: { buffer } }); 10 | 11 | worker.on('message', (msg) => { 12 | if (msg.name === 'display') { 13 | console.dir({ value: array[0] }); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /JavaScript/3-server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | const { Worker } = threads; 5 | 6 | const worker = new Worker('./3-http.js'); 7 | 8 | worker.on('message', (msg) => { 9 | if (msg.name === 'started') { 10 | console.log(`HTTP Server Started on ${msg.port}`); 11 | } 12 | }); 13 | 14 | process.on('SIGINT', async () => { 15 | await worker.terminate(); 16 | console.log('HTTP Server Stopped'); 17 | }); 18 | -------------------------------------------------------------------------------- /JavaScript/5-share.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | const { Worker } = threads; 5 | 6 | const buffer = new SharedArrayBuffer(1024); 7 | 8 | const worker = new Worker('./5-access.js', { workerData: { buffer } }); 9 | 10 | setInterval(() => { 11 | console.dir(buffer); 12 | }, 100); 13 | 14 | process.on('SIGINT', async () => { 15 | await worker.terminate(); 16 | console.log('Bye'); 17 | process.exit(0); 18 | }); 19 | -------------------------------------------------------------------------------- /JavaScript/2-master.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | const { Worker } = threads; 5 | 6 | console.dir({ master: threads }); 7 | const workerData = { text: 'Data from Master to Worker' }; 8 | const worker = new Worker('./2-worker.js', { workerData }); 9 | 10 | worker.postMessage('Message from Master to Worker'); 11 | worker.on('message', (...args) => { 12 | console.log({ args }); 13 | }); 14 | worker.on('error', (err) => { 15 | console.log(err.stack); 16 | }); 17 | worker.on('exit', (code) => { 18 | console.dir({ code }); 19 | }); 20 | 21 | setTimeout(async () => { 22 | await worker.terminate(); 23 | console.log('Terminated'); 24 | }, 1000); 25 | -------------------------------------------------------------------------------- /JavaScript/3-http.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | const http = require('node:http'); 5 | 6 | const port = 8000; 7 | 8 | threads.parentPort.postMessage({ name: 'started', port }); 9 | 10 | const routing = { 11 | '/': async (req, res) => ({ status: res.statusCode }), 12 | '/api/method': async (req, res) => ({ status: res.statusCode }), 13 | }; 14 | 15 | const types = { 16 | object: JSON.stringify, 17 | string: (s) => s, 18 | number: (n) => n.toString(), 19 | undefined: () => 'not found', 20 | }; 21 | 22 | http 23 | .createServer(async (req, res) => { 24 | const handler = routing[req.url]; 25 | if (!handler) { 26 | res.end('Handler not found'); 27 | return; 28 | } 29 | const data = await handler(req, res); 30 | const type = typeof data; 31 | const serializer = types[type]; 32 | const result = serializer(data); 33 | res.end(result); 34 | }) 35 | .listen(port); 36 | -------------------------------------------------------------------------------- /JavaScript/1-worker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const threads = require('node:worker_threads'); 4 | const { Worker } = threads; 5 | 6 | const getInheritance = (instance, parents = []) => { 7 | const parent = Object.getPrototypeOf(instance); 8 | if (!parent) return parents; 9 | parents.push(parent.constructor.name); 10 | return getInheritance(parent, parents); 11 | }; 12 | 13 | if (threads.isMainThread) { 14 | console.dir({ master: threads }); 15 | const workerData = { text: 'Data from Master to Worker' }; 16 | const worker = new Worker(__filename, { workerData }); 17 | worker.on('message', (...args) => { 18 | console.log({ args }); 19 | }); 20 | worker.on('error', (err) => { 21 | console.log(err.stack); 22 | }); 23 | worker.on('exit', (code) => { 24 | console.dir({ code }); 25 | }); 26 | console.dir(getInheritance(worker)); 27 | } else { 28 | console.dir({ worker: threads }); 29 | threads.parentPort.postMessage('Hello there!'); 30 | setTimeout(() => { 31 | const data = { text: 'Message from Worker to Master' }; 32 | threads.parentPort.postMessage(data); 33 | }, 1000); 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2024 How.Programming.Works contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------