На этой неделе я впервые создал новый поток в Ruby. Хотя я и раньше слышал термин «поток», мне не приходилось много думать об этом с точки зрения явной работы, потому что большая часть моего кода была создана для синхронного выполнения.
Это может начать описывать мою проблему, прежде чем я углублюсь в нее. В настоящее время я работаю над приложением чата, которое удаляет все чаты и сообщения, связанные с пользователем, когда он или она выходит из системы. Поскольку пользователь не может снова войти в систему, его или ее учетная запись должна быть удалена в конце концов, я застрял, думая о крайнем случае. Что, если пользователь просто не выйдет из системы, а вместо этого закроет браузер? Я бы закончил со всеми этими пользователями в базе данных, которые просто занимают место.
Я подумал, что логичным ответом будет просто удалить неактивного пользователя или пользователя, который не заявляет, что хочет оставаться в системе по истечении заданного периода времени. Я написал небольшой код в модели User, который удаляет пользователя через определенное время и столкнулся с проблемой. Мой пользовательский экземпляр отправлялся на сторону клиента только после того, как пользовательский экземпляр уже был удален.
Код работал так:
Но я хотел, чтобы мой код работал так:
Ответ буквально заключался в том, чтобы обернуть мой вызов функции в Thread.new.
Что такое поток
Поток на самом деле является сокращением от «потока выполнения». Techopedia описала его как «наименьшую единицу обработки, которая может быть выполнена в ОС». Для веб-разработки важно знать, что не все языки программирования поддерживают многопоточность, что в общих потоках могут быть реализованы разные способы.
Потоки могут быть на уровне ядра, что означает, что для каждого потока в ОС есть один языковой поток. Другие не будут иметь такого же соотношения один к одному и будут иметь предусмотренные языком потоки, известные как зеленые потоки или M:N.
JavaScript является однопоточным, поэтому вы не можете запускать несколько потоков. Это не означает, что функции нельзя запускать одновременно, но под капотом происходит что-то еще.
Многопоточный код в целом работает быстрее, что кажется вполне логичным. Вместо того, чтобы запускать одну задачу, а затем двигаться дальше, все они могут выполняться одновременно. Однако вы не можете добавлять бесконечные потоки, чтобы сделать вашу программу быстрее. Использование нескольких потоков также может вызвать другие проблемы, поскольку у вас могут возникнуть проблемы с определением порядка выполнения потоков.
В Ruby, когда вы хотите использовать несколько потоков, вы также можете использовать пул потоков. Это потребует кучу предварительно созданных потоков, которые могут запускаться по мере необходимости. Теперь, когда у вас есть задача, она будет использовать один из незанятых потоков. Если ни один поток не простаивает, он ожидает завершения задачи, прежде чем запускать задачу в потоке, который сейчас находится в режиме ожидания.
Ресурсы:
«Ruby Concurrency and Parallelism: Практическое руководство» Eqbal Quran
Распутывая рубиновые нити Тома Вея
Язык программирования Rust «Использование потоков для одновременного выполнения кода», Стив Клабник и Кэрол Николс.