На этой неделе я впервые создал новый поток в Ruby. Хотя я и раньше слышал термин «поток», мне не приходилось много думать об этом с точки зрения явной работы, потому что большая часть моего кода была создана для синхронного выполнения.

Это может начать описывать мою проблему, прежде чем я углублюсь в нее. В настоящее время я работаю над приложением чата, которое удаляет все чаты и сообщения, связанные с пользователем, когда он или она выходит из системы. Поскольку пользователь не может снова войти в систему, его или ее учетная запись должна быть удалена в конце концов, я застрял, думая о крайнем случае. Что, если пользователь просто не выйдет из системы, а вместо этого закроет браузер? Я бы закончил со всеми этими пользователями в базе данных, которые просто занимают место.

Я подумал, что логичным ответом будет просто удалить неактивного пользователя или пользователя, который не заявляет, что хочет оставаться в системе по истечении заданного периода времени. Я написал небольшой код в модели User, который удаляет пользователя через определенное время и столкнулся с проблемой. Мой пользовательский экземпляр отправлялся на сторону клиента только после того, как пользовательский экземпляр уже был удален.

Код работал так:

Но я хотел, чтобы мой код работал так:

Ответ буквально заключался в том, чтобы обернуть мой вызов функции в Thread.new.

Что такое поток

Поток на самом деле является сокращением от «потока выполнения». Techopedia описала его как «наименьшую единицу обработки, которая может быть выполнена в ОС». Для веб-разработки важно знать, что не все языки программирования поддерживают многопоточность, что в общих потоках могут быть реализованы разные способы.

Потоки могут быть на уровне ядра, что означает, что для каждого потока в ОС есть один языковой поток. Другие не будут иметь такого же соотношения один к одному и будут иметь предусмотренные языком потоки, известные как зеленые потоки или M:N.

JavaScript является однопоточным, поэтому вы не можете запускать несколько потоков. Это не означает, что функции нельзя запускать одновременно, но под капотом происходит что-то еще.

Многопоточный код в целом работает быстрее, что кажется вполне логичным. Вместо того, чтобы запускать одну задачу, а затем двигаться дальше, все они могут выполняться одновременно. Однако вы не можете добавлять бесконечные потоки, чтобы сделать вашу программу быстрее. Использование нескольких потоков также может вызвать другие проблемы, поскольку у вас могут возникнуть проблемы с определением порядка выполнения потоков.

В Ruby, когда вы хотите использовать несколько потоков, вы также можете использовать пул потоков. Это потребует кучу предварительно созданных потоков, которые могут запускаться по мере необходимости. Теперь, когда у вас есть задача, она будет использовать один из незанятых потоков. Если ни один поток не простаивает, он ожидает завершения задачи, прежде чем запускать задачу в потоке, который сейчас находится в режиме ожидания.

Ресурсы:

«Ruby Concurrency and Parallelism: Практическое руководство» Eqbal Quran

Распутывая рубиновые нити Тома Вея

Язык программирования Rust «Использование потоков для одновременного выполнения кода», Стив Клабник и Кэрол Николс.