Что можно из нитки сделать: Что сделать из ниток для вязания своими руками
Что сделать из ниток для вязания своими руками
Всех приветствую, друзья!
Продолжая тему использования остатков ниток, хочу предложить вам несколько интересных идей, что можно сделать из ниток для вязания своими руками. О том, что связать, мы уже говорили, а если вязать не хочется или ниток маловато? Кроме того они могут быть совсем короткими, все равно жалко просто так выбрасывать.
Что сделать из толстых шерстяных ниток для вязания
Самое простое, что можно сделать из шерстяных ниток – это декор самых разных вещей нитками, которыми предмет просто напросто обматывается вокруг.
Это и декор цветочных горшков, и банок под подсвечники, и бутылок под вазы, и рамок для фотографий, и браслетов, и маленькие декоративные елочки так можно сделать на картонном конусе, и большие буквы для разных декораций и празднований юбилеев.
Как сделать подсвечник из банки я уже показывала.
Еще раз напомню, как выполнять подобный декор.
Для украшения бутылки, например, потребуются нитки, клей и ножницы. Клей лучше брать более надежный, например «Момент».
Как сделать:
- Для начала промазывают клеем бутылку в верхней части вокруг горлышка.
- Прикладывают к этому месту нитку от клубка, прижимают и начинают обматывать всю бутылку вокруг, плотно подгоняя ниточки друг к другу, чтобы не было просветов.
- Когда дошли до донышка, опять промазывают клеем бутылку в нижней части.
- Сделав последний оборот, нить обрезают.
Умельцы мастерят из толстых ниток разных зверушек, птичек, кукол. Заинтересовавшиеся, думаю, легко смогут найти нужный мастер класс. Посмотреть как сделать синичку, можно здесь к примеру: https://www.diyideas.ru/pages/9859.html
Из коротких ниточек удобно делать разные перышки.
Несколько коротких нитей располагают поперек на проволочке, прижимая друг к другу, завязывают и расправляют кончики. Чтобы нитки лучше держали форму, их обмакивают в раствор желатина или разбавленный с водой клей ПВА.
Затем полученную заготовку расправляют и оставляют для просушки.
При необходимости подрезают до придания нужной формы.
Если у вас много старых цветных ниток, из которых уже не возможно что то связать, можно сделать чудесные пушистые подушки и коврики, подробное описание и схемы рисунков у нас имеются.
Ну и помпоны, конечно, можно сделать из вязальных ниток и поделки из них.
Уют из помпонов. Как сделать помпоны из пряжи. Поделки из помпонов
Мандала своими руками плетеная из ниток
Ставшие модными нынче мандалы можно сплести из ниток.
Для этого потребуются какие-нибудь палочки типа бамбуковых и сами нитки разных цветов.
Палочки склеивают попарно крест-накрест и от середины наматывают на них нитки. Чтобы все было понятно и наглядно, посмотрите это видео:
Панно из ниток и гвоздей в технике стринг-арт
Не новая уже идея, но замечательная просто. Такие стильные панно, картины, подвески можно сделать из простых тонких ниток в технике стринг – арт.
Для панно потребуется основание – картон, фанера, пенопласт и прочие материалы подойдут, много мелких (по моему мнению, лучше декоративных с красивыми шляпками, но необязательно) гвоздиков и нитки.
Как сделать:
На основании карандашом рисуют контур будущего изображения, можно использовать какой-нибудь шаблон, найти в интернете картинку, распечатать и вырезать.
По контуру рисунка на равном небольшом расстоянии друг от друга вбивают гвоздики.
А затем наматывают вокруг гвоздей нитки, как бы закрашивая ими часть рисунка.
Причем можно «закрашивать» какого то конкретного «героя» или сделать наоборот – замотать нитками пространство вокруг него. Тоже смотрится интересно и необычно.
Ажурные шары из ниток
Ставший популярным вид творчества – ажурные шары из ниток и клея. Такие шары являются прекрасным элементом декора помещений, как большие, так и множество маленьких в единой композиции.
И тут фантазии безграничны. В такой технике можно создать и люстры, и вазы, из шариков из ниток можно сделать елочные игрушки, снеговичков, и даже пасхальные яйца.
Как сделать шар из ниток:
Кроме ниток и клея ПВА потребуется еще обычный воздушный шар круглой формы. Его нужно надуть до нужного размера и завязать.
Тонкие нитки с помощью иголки пропускают через пластиковый пузырек с клеем и начинают обматывать шарик в хаотичном порядке.
После просушки присохшие нитки нужно отделить от шарика тупым предметом, осторожно, чтобы шар не лопнул.
А затем уже протыкают шар, выпускают из него воздух и вынимают сквозь ниточки.
Аналогичным образом делают пасхальные яйца, только шары нужно надувать продолговатой формы.
А вот как сделать такие великолепные вазы из ниток, их создатель дизайнер Anne Honeyman из Великобритании держит в тайне. Ну, мы можем, хотя бы полюбоваться.
Картины из ткани и ниток: ниткография
Удивительный вид творчества – ниткография. Даже не умея вязать, вышивать и рисовать, можно сделать из ткани и ниток чудесные картины.
Материалы, которые потребуются:
- остатки цветных ниток для вязания
- кусок ткани для основы, либо фанера, картон, ковролин
- клей ПВА
- ножницы, кисточка, зубочистки.
Как сделать:
- На основу нанести контур рисунка при помощи карандаша.
- Нитки нужно нарезать на кусочки небольшой длины, так удобнее с ним работать.
- С помощью кисти нанести на небольшой участок рисунка клей.
- Уложить нитку, прижимая ее зубочисткой, продвигаясь от контура к центру.
- Излишки нити обрезать ножницами.
- В завершение проложить контрастную нить вдоль всего контура, чтобы подчеркнуть рисунок.
Конечно, тут надо иметь и фантазию, и творческую мысль, и терпение.
Но оказывается даже просто красивый декор разных вещей таким образом можно легко сделать: одежды, сумочек, абажуров, подушек, можно украсить подлокотники дивана.
Посмотрите, как это делает Ольга Волкова:
Вот такие у меня мысли и идеи, что можно сделать из ниток для вязания своими руками. Что вы думаете по этому поводу?С уважением, автор блога «Уют и тепло моего дома» Ольга Смирнова
7 DIY идей – DIY и мастер-классы
Что можно сделать из ниток для декора дома своими руками.
Декор для дома, сделанный своими руками, — это всегда красиво, уютно и довольно бюджетно. А вы знаете, что нитками можно не только шить или вязать? Оказывается, из них можно сделать оригинальные поделки для дома, которые не требуют особых навыков декорирования и больших затрат. Если у вас давно лежат без дела несколько клубков разноцветных ниток, воспользуйтесь этими вдохновляющими идеями.
1. Шары из ниток и воздушных шаров
2. Панно из ниток и гвоздей
Еще одна интересная идея — изящное панно из ниток, натянутых на небольшие гвозди. Посмотрите пошаговые фото или видео с мастер-классом, и вы сможете самостоятельно смастерить такое панно из наиболее доступных материалов.
3. Декор из помпонов
Помпоны из ниток очень просты в изготовлении, из них можно сделать забавные и уютные элементы декора. Посмотрите на эти фотографии — наверняка вам захочется привнести в свой интерьер немного мягких и пушистых помпонов…
4. Вазы из бутылок
С помошью ниток можно также создать оригинальные вазы. Для этого вам понадобится стеклянная бутылка (или банка), цветные нитки и клей ПВА. Нанесите клей на поверхность бутылки, а затем как можно туже наматывайте пряжу на бутылку так, чтобы между нитками не оставалось просветов. Просто и красиво!
5. Буквы из ниток
Чтобы сделать яркие интерьерные буквы из ниток вам понадобится плотный картон, ножницы и нитки разных оттенков. Эти буквы можно также украсить декоративными бусинами, пуговицами или цветами. Разноцветными буквами в доме можно украсить комод, подоконник, полку или диван.
6. Настенный декор из ниток
С помощью ниток можно также сделать нарядный декор для стен. В плане формы и исполнения — здесь простор для творчества и фантазии! Например, хорошая идея — намотать разноцветные нитки на обычные пяльца для вышивки.
Или привязать разноцветные нити различной длины на медную трубку. Посмотрите, как просто смастерить такой аксессуар своими руками — получается очень стильно!
7. Плетеная мандала из ниток
Мандала — сакральный геометрический символ, используемый при медитациях в буддизме, который прекрасно смотрится в интерьере в качестве декора.
Чтобы сплести такую мандалу вам понадобятся 8 одинаковых палочек, разноцветные нитки и ножницы. Существует несколько способов плетения мандалы, самый простой способ — на пошаговом фото внизу.
Рекомендуем почитать:
Простые панно своими руками: 7 мастер-классов
10 DIY идей декора бечевкой
Фотографии: decorin.me, svadbalist.ru, etsy.com, pinterest.com, idesign.today
8 идей использования остатков старой пряжи: мастер-классы с фото, #Лучшедома
Чем заняться на карантине? На самом деле идей очень много, особенно если у вас есть какое-нибудь интересное хобби. К примеру, вы увлечены вязанием, и у вас точно в доме много-много уже значительно истощившихся клубочков с нитками. И сейчас их вполне можно подо что-то приспособить, пока мы все следуем рекомендациям по самоизоляции — #лучшедома. Так что не выбрасывайте старую пряжу — идеи полезного ее использования мы собрали для вас в этом материале. Оказывается, так много всего полезного для дома можно создать из остатков ниток!
№ 1 — Коврик для дачиОдин из вариантов коврика на дачуЭто одна из самых сложных идей использования остатков пряжи, но для опытной рукодельницы реализация ее не будет проблемой. Коврик для дачи или дома, сделанный из ниток, добавит уюта, может стать отличной лежанкой для вашего питомца или же превратится в прикроватный коврик, и вам не придется опускать ноги на холодный пол по утрам. Словом, применение ему найти можно легко. Давайте посмотрим, как можно сделать такой коврик!
Мягкий коврик для вас и ваших питомцевШаг 1. Для работы возьмите не только старые вязальные нитки, но и кусочки ткани. Если их нет, то можете взять старую ненужную футболку и использовать ее. Из ткани сделайте основу для коврика. Нарежьте материал на длинные (желательно) полоски шириной 2-3 см и сплетите из них много косичек. Плести нужно туго. А из готовых косичек соберите круглую (квадратную) основу. Просто сшейте их между собой или сплетите крючком.
Вот такие косички у вас должны получитьсяКак вариант соединить косички в основу можно, просто связав ихШаг 2. Готовую основу нужно оформить. Но для начала сделайте из вязальных ниток небольшой бортик шириной примерно в 10 петель. Он поможет оформить края будущего коврика.
Сделайте бортик для коврикаШаг 3. Пришейте готовый бортик к основе из ткани по краю.
Пришейте бортик по краю коврикаШаг 4. Теперь начинайте декорировать будущий коврик. Лучше всего начать с середины. В центре можно сделать оригинальные круги, в которых основу составят кольца из пластика. Для маленького колечка используйте обычное кольцо от пластиковой бутылки, которое фиксирует пробку на ней. Обмотайте колечко ниткой и закрепите ее.
Начните оформлять сердцевинуШаг 5. Далее обвяжите кольцо по кругу столбиком. Чтобы работа шла быстрее, можете использовать толстые нитки. Готовую сердцевину можно обвязать контрастного цвета нитью для красоты.
Обвяжите колечкоВот так можно сделатьШаг 6. По такому же принципу изготовьте второе кольцо, но большего диаметра. Можно взять колечко от пластиковой банки.
Обвяжите столбиком кольцо побольшеШаг 7. По такому же принципу — обвязывая пластиковые кольца от банок и бутылок — подготовьте и другие декоративные элементы. Просто используйте разную по цвету пряжу для каждого. Желательно, чтобы по толщине элементы были более-менее одинаковые — тогда коврик не будет иметь грубых перепадов высот.
Подготовьте и другие элементы декораШаг 8. Распределите готовые декоративные элементы по всей основе, чтобы получился красивый узор. Пришейте их к поверхности. Дополнительно можете украсить коврик бантиками, ленточками и другими элементами.
Пришейте кружочки к основе№ 2 — Подставки под горячееТакие подставки под горячее сделают любое чаепитие уютнееНа заметку! По такому же принципу можно связать и накладку на стул или табурет. Еще один способ потратить остатки пряжи.
Эта идея подойдет только для вязальщиц, владеющих крючком. Из остатков пряжи большую салфетку, конечно, не свяжешь, а вот милые маленькие подставки под горячие кружки — вполне.
Просто выберите подходящую вам схему, возьмите крючок и приступайте к вязке. Совсем скоро у вас на столе появятся небольшие яркие и симпатичные мини-салфетки, на которые так удобно ставить чашки с чаем во время дружеских бесед.
Видео — Мастер-класс по вязанию подставки под горячее для чашки№ 3 — Сидение на стул из помпоновСидение на стул из помпоновСовет! Чтобы чашки не падали, стоит сделать такие подставки максимально ровными и гладкими. Схемы вязки с кружевами использовать не рекомендуем.
Из пряжи можно сделать и оригинальную, а главное — мягкую сидушку. Для этого, правда, снова придется поработать руками и сделать из ниток множество помпонов.
Шаг 1. Сначала накрутите помпоны. Для этого на два пальца левой руки — указательный и средний, сложенные вместе — начинайте наматывать вязальные нитки.
Наматывать помпоны на пальцы очень удобноШаг 2. Когда на пальцах сформируется «клубочек», отрежьте нитку от основного клубка, а получившийся моточек перевяжите посередине (между двумя пальцами) ниткой в цвет (такой кусочек нитки лучше заготовить заранее). Отрезок нитки для перевязки делайте побольше — его концы нам еще пригодятся.
Перевяжите моточек посерединеШаг 3. Разрежьте нитки в полученном клубочке посередине сгибов.
Разрежьте нитки на сгибахШаг 4. У вас получился первый помпон. Сделайте множество таких помпонов из ниток разного цвета, повторяя шаги 1-3.
Сделайте много разноцветных помпоновШаг 5. Возьмите основу — коврик, который часто используется в ванной или на кухне. Он имеет множество дырочек.
Такой коврик можно купить в хозяйственном магазинеШаг 6. Аккуратно ножницами протягивайте нитки, перевязывающие помпон, через отверстия в коврике. Каждую нитку — через свою дырочку. У одного помпона нитки должны проходить через соседние дырочки.
Аккуратно проденьте нитки через дырочки в коврикеШаг 7. Свяжите концы ниток одного помпона на изнаночной стороне коврика.
Закрепите помпон, завязав ниткиШаг 8. По такому принципу украсьте всю поверхность коврика помпонами.
Украсьте весь коврик помпонами№ 4 — Мобиль на детскую кроваткуМобиль на детскую кроваткуТем, у кого в семье скоро появится малыш, этот мастер-класс точно понравится. Из остатков пряжи можно сделать яркий и безопасный мобиль для крохи. А для тех, кто не знает, что это, рассказываем: мобиль — это конструкция с игрушками, которая подвешивается над детской кроваткой. Дети очень любят наблюдать за болтающимися фигурками. Итак, как же сделать мобиль из пряжи?
Шаг 1. Для создания игрушки вам потребуются кусочек картона, пяльцы для вышивания, ножницы, игла и, конечно, сама пряжа. Приготовьте все сразу.
Приготовьте все необходимое для работыШаг 2. Вспомните, как в предыдущем мастер-классе мы делали помпоны. Теперь тоже делайте их, но вместо пальцев для наматывания ниток используйте кусочек картона.
Начните делать помпоныШаг 3. Также посередине перевяжите получившиеся моточки ниткой в цвет.
Перетяните ниткой будущий помпонШаг 4. После разрежьте нитки на сгибах посередине.
Разрежьте края моточкаШаг 5. Сделайте много-много таких помпонов.
Сделайте достаточное количество помпоновШаг 6. Возьмите обруч от пяльцев и обмотайте его вязальными нитками.
Обмотайте пяльцы ниткамиШаг 7. Вот такой обруч должен получиться. Теперь приготовьте три длинных нитки и свяжите их между собой.
Приготовьте нитки для крепления помпоновШаг 8. Пришейте помпоны к ниткам, а на место, где они связаны, прицепите помпон побольше. Сверху над ним сделайте петельку.
Пришейте помпоны к ниткамШаг 9. Закрепите нитки с помпонами на кольце от пяльцев так, чтобы центральный помпон был с одной стороны плоскости круга, а нитки с маленькими помпонами — с другой. Мобиль готов. Его за счет петельки легко подвесить над кроваткой, используя специальное приспособление.
Закрепите помпоны на пяльцах№ 5 — Мозаика из микро-клубочковОригинальная мозаика из клубочковЕще один оригинальный способ потратить с пользой остатки пряжи — сделать детскую мозаику из маленьких клубочков или микро-помпончиков. Под нее можно приспособить «емкость» с рамкой, внутри которой можно раскрасить разными цветами участки основания. По цвету они должны подходить к выбранной пряже.
Рассказывать, как делать помпоны или клубочки, не будем — выше есть примеры. Здесь действовать нужно точно так же, но делать очень маленькие элементы. Количество клубочков или помпоном нужного цвета должно быть таким, чтобы при плотной укладке их внутри рамки на зоне такого же цвета она была полностью ими закрыта.
Мозаика абсолютно безопасна для детей старше трех лет. Дети с увлечением сортируют элементы по цветам.
№ 6 — Цветочный горшокОригинальные горшки для цветов, декорированные пряжейСовет! Малышам такую мозаику из пряжи давать не стоит, так как клубочки слишком маленькие и могут представлять опасность. Но для крошек вполне можно сделать вариант с более крупными элементами.
Из остатков пряжи можно сделать и интересный декор для цветочных горшков. Если у вас дома много зеленых растений, то почему бы не украсить места их проживания разноцветными нитками? И да, уметь вязать совершенно не обязательно! В этом случае все намного проще.
Шаг 1. Для создания такого «нитяного» декора вам, помимо остатков пряжи, потребуются клей ПВА и сам цветочный горшок. Пусть все лежит под рукой.
Приготовьте все необходимоеШаг 2. Возьмите клей и нанесите его под ободком горшка тонкой полоской.
Для приклеивания ниток подойдет обычный ПВАШаг 3. Далее возьмите выбранный вариант пряжи и начните приклеивать ниточку на клей.
Приклеивайте пряжу по кругуШаг 4. Планомерно обматывайте горшок ниткой, приклеивая ее на ПВА. По мере работы добавляйте на поверхность горшка клей.
Обматывайте пряжей горшочекШаг 5. Через каждые несколько витков поджимайте друг к другу нитки, чтобы они сидели на горшочке плотно.
Поджимайте нитки, чтобы они сидели плотноШаг 6. Примерно на трети высоты горшка обрежьте нитку, подклейте оставшийся хвостик клеем.
Обрежьте нитку, когда закончите работать с одним цветомШаг 7. По такому же принципу снова начните обклеивать горшок, но уже нитками другого цвета.
Используйте нитки разного цвета для декораШаг 8. И далее обмотайте горшок ниткой третьего цвета.
Можно использовать разные комбинации цветовШаг 9. Хвостик последней нитки также обязательно хорошо проклейте клеем.
Фиксируйте хвостики ниток на клейШаг 10. Чтобы горшочек меньше пачкался и был прост в уходе, покройте пряжу лаком.
Покройте горшочек лакомШаг 11. Места, где нитки были обрезаны, дополнительно укрепите: приклейте на эти участки бусины, используя клеевой пистолет.
Дополнительно зафиксируйте хвостики ниток бусинами№ 7 — Свитер для настенных часовОригинальные часы в свитере идеально будут смотреться в яркой кухнеСовет! Используйте разноцветную пряжу на одном горшке. Тогда он будет выглядеть ярче и веселее.
Если вы любите необычные яркие вещи, то украсьте остатками пряжи настенные часы. У многих из них есть достаточно широкий ободок вокруг циферблата. И вот как раз его можно обвязать/обмотать остатками пряжи, подобрав ее по цветам.
Это решение подойдет тем, кто любит что-то необычное. Конечно, такой «свитер» для часов впишется далеко не в каждый интерьер. Но с другой стороны, играя с цветами, вы сможете придумать, как реализовать идею практически в любых условиях.
№ 8 — Носочки для стульевМилые и забавные носочки для стульевСовет! Помните, как в мастер-классе по горшочкам мы покрывали нитки лаком? С часами можно поступить так же! Тогда пряжа будет намного легче очищаться от пыли во время уборки.
Если у вас очень нежное покрытие на полу или вы слишком громко двигаете стулья, то, использовав эту идею, вы решите и ту, и эту проблему. Стулья в таких носочках на ножках будут передвигаться максимально тихо, не нарушая сон домочадцев в утренние часы, а полы останутся целыми и без царапин.
На один такой носочек тратится совсем мало пряжи. Так что остатки ниток вполне сгодятся для этой работы. Вязать лучше всего крючком и можно использовать самые простые приемы вязания. Мастер-класс по созданию таких изделий представлен в видео ниже.
Видео — Вяжем крючком носочки на стулСовет! Чтобы носочки не слетали, зафиксируйте их на ножках резиночками, вшитыми в верхнюю часть носочка.
Можно придумать еще массу способов, как израсходовать остатки вязальных ниток и не выбросить их просто так. Делайте забавные игрушки или бижутерию, картины из ниток, вяжите одежду для кукол… Словом, включайте свою фантазию и подумайте, что вам действительно нужно дома или на даче. И идея, как реализовать остатки пряжи, уж точно не заставит себя ждать.
Поделки из ниток мулине и шерсти своими руками (фото)
Большинство представительниц женского пола, сидят дома и занимаются рукоделием. У них, всегда имеются в наличии некоторое количество неиспользованных мотков нитей. Избавится от них, вроде бы жалко. Мы подскажем вам, в каком русле их применить. Они могут пригодиться в создании разнообразных поделок из ниток.
Эти остатки ниток, можно использовать в украшении интерьера, в виде поделки из шерстяных ниток, сделать интересные игрушки для ваших детей и многое другое, на что способна ваша фантазия. Давайте рассмотрим самые интересные поделки из ниток, которые пригодятся даже в повседневной жизни.
Дружеский браслет
С помощью нитей мулине, молодые люди плетут модные и экстравагантные браслеты, именуемые в народе, как фенечки. Такие поделки из ниток мулине, как феньки, создавались много сотен лет назад в индейских племенах. Фенечки, являлись символом дружелюбия. В других странах, они использовались, как зашифрованная информация для того, кому принадлежали. Для представителей движения хиппи, такие браслеты служили, как информационная база, по которой можно узнать семейный статус или предпочтения в музыкальном направлении. Для того, чтобы самостоятельно сделать своими руками фенечки из мулине, необходимо приобрести подходящую фурнитуру.
Итак, нам необходимо:
- нити мулине, цветовую гамму вы подбираете самостоятельно, на ваш вкус;
- несколько булавок;
- острые ножницы.
Количество ниток зависит от того, какой браслет вы желаете по ширине. Если плести очень красивый браслет, тогда вам понадобится восемь цветов нитей. Протяженность нитей, не должна быть меньше 1 метра, либо браслет получится коротким. Перед тем, как начать, мулине нужно прикрепить к твердой поверхности. Это надо сделать обязательно, так как браслет будет двигаться в разные стороны. Возьмите нитку, находящуюся справой стороны. Ею необходимо обвязывать нитку двумя узелками. Продолжайте делать такие манипуляции до самого конца. Следующие ярусы, необходимо плести, как и первоначальный. Последняя нитка, будет меняться. Продолжая плетение, можно создать своими руками невероятный и красочный браслет на руку из ниток мулине. Неважно сколько вам лет, такая фенечка понравится, как маленьким, так и взрослым людям.
Создание цыпленка из нитей
Если у вас осталось немного шерстяных ниток, от предыдущего рукоделия, можно сделать своими руками, для своих детей прекрасную игрушку, в виде цыпленка. Такие поделки, не оставят равнодушными ваших детей, потому что выглядят они интересно и ярко. С ними очень интересно играть. Делаются такие поделки, довольно легко и скоро. А главное, вы не потратите много денег.
Давайте рассмотрим, какая фурнитура нам нужна:
- несколько шерстяных желтых ниток;
- канцелярского клея;
- плотный картон;
- ножницы;
- красного оттенка бумага.
Из плотного картона, вырезаем 4 колечка. Два первых, будут небольшой окружности, а два вторых будут по больше. Сложите вместе первые два колечка и наматывайте на них определенное количество шерстяных нитей. Необходимо разрезать наши нитки, продев ножницы между кольцами. После этого, просуньте нитку сквозь кольца и завяжите. Вытягивайте получившийся комок из шерстяных ниток и проделывайте такие манипуляции с оставшимися кольцами. У нас получились голова и туловище цыпленка.
Канцелярским прозрачным клеем, приклейте голову цыпленка к туловищу. Далее, начинаем делать красный клюв и две маленькие лапки. Клюв вырезайте из бумаги и тоже клейте к голове. Бусины необходимо поместить туда, где глазки. Вот и готова прекрасная игрушка из шерстяных ниток и клея, в виде цыпленка. Такие поделки, можно сделать для детей либо украсить пасхальный стол, а также использовать поделки в кукольном домашнем театре.
Учимся делать снеговика
Давайте рассмотрим, как можно сделать такую поделку, как снеговик из ниток и клея. Для этого нам понадобится:
- хлопковые либо вискозные нити;
- канцелярский клей;
- шарики надувные;
- иголка.
Фляжку с клеем необходимо проткнуть иголкой с нитью насквозь. Потом, протяните ее через всю бутылку. Надуйте воздушные шарики, три из них, станут туловищем, а два послужат руками снеговика. Обматывайте каждый шарик, смоченной в бутылке клея, ниткой. Делайте это плотным слоем, чтобы нитка не провисала. Оставьте шарики для того, чтобы остатки клея полностью высохли.
Теперь начинается самое интересное. После того, как капли клея высохли, проткните все шарики иголкой и быстренько удаляйте их. У вас получились первые заготовки для нашей поделки снеговика. Склейте шары клеем друг с другом. Последние штрихи заключаются в украшении снеговика. Прислушайтесь к вашей фантазии.
Парик с помощью ниток
Мы рассмотрели несколько видов поделок, которые можно сделать легко и быстро своими руками. При этом, хотим вам показать, как сделать парик. Пусть, даже такая поделка, может показаться странной. Для тех, кто готов научиться делать, необходимо потренироваться на кукле. Для этого, свяжите на кукольную голову, с помощью крючка, шапочку. В остальном, нам необходимы такие материалы:
- нитки для парика;
- крючок;
- тонкая резинка;
- острые ножницы.
Небольшой мастер-класс вязания шапочки под парик. Сделайте первые три воздушные петельки. Потом, свяжите столбцы и соедините в кольцо. Вяжите ряды до тех пор, пока не дойдете до конца. Тонкая резинка просовывается в самый последний ярус. Вот и все, шапочка на голову куклы готова.
Сделайте первую примерку, если все подходит, продолжаем делать мастер-класс. Определитесь, какую длину вы хотите, и только тогда отматывайте нить нужной протяженности. Толстую нить, сложите вдвое и вплетаем в шапочку. Нарезайте и вплетайте нити, можете их распускать, чтобы шевелюра была пышной.
Нитку начинаем крепить в последнем ряду. Делайте это очень аккуратно, чтобы волосы можно было поднимать вверх. Мы раскроем вам один секрет, как это можно сделать. Возьмите крючок, и проведите нить под нижний ярус. В петлицу, просовываем нитку и стягиваем, но не перестарайтесь.
Заплетите весь парик, кроме верхушки, ее лучше сделать по-другому. Всовывайте нить в каждый столбец в шапке. Не забывайте тщательно делать пробор. Только, после этого, парик будет смотреться прекрасно и аккуратно. С помощью ножниц, подравняйте длину, сделайте ее ровной по всей голове. Если у вас есть навыки, можно сделать интересную прическу. Наша работа закончена, а интересная поделка из ниток, станет интересной забавой для вашей дочери.
Мы рассказали вам, что можно сделать своими руками из оставшихся мотков ниток. Это не весь перечень поделок, которые являются занимательным рукоделием. С помощью своей фантазии, вы сможете сделать больше. И ваши поделки из ниток, принесут радость и умиление окружающим, так как поделки из ниток, это настоящее рукоделие.
Видео: Учимся делать снеговика
Поделки из ниток и пряжи
Ёлочка из цепочки воздушных петель крючкомЁлочку из пряжи из воздушных петель для украшения дома к празднику можно связать крючком легко и быстро, и украсить по своему желанию,…
Иногда в ближайших магазинах товаров для рукоделия достаточно сложно найти тычинки нужного цвета и нужного Вам количества. В данном мастер-классе…
Ажурные бабочки из ниток или пряжи своими рукамиХочу представить Вашему вниманию отличную идею для украшения различных изделий ручной работы — ажурных бабочек из ниток или пряжи. Давно…
Топиарий из клубков пряжи «Рукодельница»На день рожденья приятельницы, которая очень красиво вяжет, решила сделать топиарий из клубочков пряжи. Но не обычное деревце, а которое …
Объемная ёлка из ниток и пряжиДо Нового года осталось совсем чуть-чуть и все мы стараемся украсить свой дом. Хочется предложить Вам еще один очень интересный вариант бюджетной…
Подвески-ёлочки, ёлочки-магнитики из пряжиТак хочется на Новый год всем подарить сувенирчики. Вот и возникла идея с магнитиками-ёлочками из пряжи. А что получилось судить и…
Вязаная крючком ёлочка с ножками. Ёлка из пряжи «Травка»Стремительно приближаются новогодние праздники, и все мы с Вами думаем, как украсить свой дом. Помимо основной «новогодней красавицы» люди часто…
Поделка из пряжи и проволоки: рождественский ангелочек. Оксана Жмаева — «Весёлые моталки»Сегодня я решила сделать небольшой обзор своих работ, иллюстрирующий, какие интересные и полезные поделки из пряжи и проволоки можно сделать …
Цветы из шпагата и пряжиЯркие радужные декоративные веточки из ниток для украшения интерьера детской комнаты очень просто сделать самостоятельно. Материалов для такого творчества, я…
Детская поделка из пряжи «Осьминог»Осьминог из ниток – детская, очень забавная поделка для детей от 4-5 лет. И поиграть с такой поделкой можно. А…
Топиарий из пряжи «Травка»Прекрасной альтернативой живым цветам сейчас служат не только комнатное горшечное растение, но и декоративное деревце – топиарий, которые сейчас стали…
Объёмный топиарий из ниток «Нежность»Недавно в магазине я увидела оригинальную дамскую пепельницу и у меня в голове, как у любого творческого человека, из этой…
Поделки из ниток. Идеи для детского творчества и не только
Творчество — вещь не имеющая границ, ведь создать красивую и интересные вещи можно сделать из чего угодно, например поделки из простых ниток. Превратите создание поделок в интересное и полезное времяпровождение вместе с ребенком. А мы лишь расскажем, как сделать самые интересные поделки из ниток своими руками.
Поделки из ниток своими руками:
Поделка «Единорог» из ниток. Подвеска
Милая нежно-розовая поделка из ниток может стать украшением комнаты юной принцессы. А главное — сделать ее очень просто.
Нам понадобится:
- Деревянное кольцо
- Вязальные нити (белого и розового цвета)
- Палочки для мороженного
- Клей-пистолет или момент
- Украшения (розочки)
- Цветной картон (перламутровый)
- Ленты и нити (пастельных тонов)
Все необходимые предметы можно легко приобрести в любом магазине творчества.
- Возьмите деревянное кольцо. Плотно обмотайте его белой нитью так, чтобы не было видно пробелов. Кончики свяжите и аккуратно обрежьте, оставив нить длиной примерно 15-20 см, чтобы поделку можно было повесить на эту нить.
- Создаем ушки единорога. Обрежьте палочки из-под мороженного до нужных размеров и склейте между собой так, чтобы получился угол. Основание второго ушка сделайте по тому же принципу.
- Обмотайте их белой нитью также как кольцо. Обматывайте сначала одну палочку не доходя до места склеивания его с другой. Угол обмотайте отдельно. Затем вторую палочку. Второе ухо оберните нитью в точности, как и первое.
- Возьмите розовую нить и звездой оберните кольцо несколько раз, чтобы получился узор похожий на паутинку.
- Приклейте ушки к кольцу с задней стороны при помощи клея-пистолета или момента.
- Из цветного картона сверните конус и склейте. Можно купить отдельно заготовку для будущего рога. Приклейте его к кольцу между ушек.
- Линии склеивания деталей украсьте с помощью декоративных цветочков розочек.
- Осталось лишь прикрепить цветные ленты к нижней части кольца. Готово!
Подробнее как сделать поделку «Единорог» из ниток можно увидеть в видео ниже:
https://www.instagram.com/p/BliLmVFnvp8/
Поделка «Собачка» из нити. Аппликация для самых маленьких
Лучший способ привлечь к творчеству самого маленького ребенка, это сделать с ним аппликации. Создавать ее очень просто, зато пользы от нее много. Ребенок учится аккуратности, развивает мелкую моторику и внимание.
Нам понадобится:
- Вязальные нити разных цветов
- Клей ПВА
- Цветной картон (1 лист)
- Шаблон собаки (по желанию)
- Карандаш
- Пластиковые глазки (по желанию)
Шаблоны с собачками вы можете найти сразу после пошаговой инструкции.
- Наметьте с помощью карандаша контуры собаки, используя шаблон.
- Смажьте клеем носик собачки. Возьмите черную нить и улиткой сверните ее по кругу на носике. С этим делом стоит помочь малышу, если у него плохо получается.
- Нарежьте мелко цветные нитки и положите их в разные мисочки по цветам.
- Смажьте клеем собаку не выходя за контуры и с помощью пушистых ниточек заполните все детали поделки.
- Когда собачка будет полностью в «шерстке» из нитки сделайте ротик и приклейте глазки.
Поделка «Дерево» из ниток. Аппликация
Нам понадобится:
- Лист белой бумаги
- Цветные карандаши
- Вязальные нити (кусочки)
Оставшиеся от вязания нити и даже самые маленькие кусочки не стоит выбрасывать. Ведь из них ребенок может делать аппликации.
- На листе бумаги нарисуйте ствол дерева, и наметьте контуры лиственной части.
- Нарежьте цветные нити оттенков листвы (красные, желтые, коричневые, зеленые) на мелкие кусочки.
- Смажьте верхнюю часть дерева и приклеивайте кусочки ниток. Устроить листопад можно также нанеся капельку клея на пространство картины и приклеив пару ниточек.
- Дорисуйте остальную часть картины: землю, солнце и все, чего захочется ребенку.
Поделка «Воздушные шары» из ниток
Эти шарики могут стать частью самого интересного дизайнерского решения. Поэтому польза этой поделки двойная: интересное занятие для ребенка и красивый интерьер — для мамы.
Нам понадобится:
- Нити (вязальные или швейные)
- Воздушный шарик (количество зависит от того, сколько шаров вы хотите сделать)
- Клей ПВА
Определитесь из какой нити вы хотите сделать поделку. От этого зависит техника исполнения.
Из вязальной нити:
- Надуйте воздушный шар небольшого размера, чтобы он был кругленькой формы.
- Обильно смажьте шарик клеем и начните обматывать его нитью, придерживая за хвостик. Заматывая шар, оставляйте небольшие промежутки. Сверху кистью смочите нити клеем.
- Дайте шарику высохнуть. После полного высыхания лопните шарик внутри и аккуратно просуньте его через отверстие в шаре из ниток. Готово!
Из швейных ниток:
- Вденьте в иголку нить и проткните ей флакончик с клеем. Теперь нить будет сразу пропитана клеем и будет хорошо фиксироваться.
- Надуйте шарик и обмотайте нитью. Дайте просохнуть поделке, а после лопните шар и уберите.
Другие идеи поделок из ниток с ребенком
- Аппликация — лучший вариант поделок для малышей. Возьмите нитки и создайте милые объемные портреты:
- Отличная идея подвески из ниток для масленицы. Здесь есть все атрибуты: красно-солнце и «соломенные» фигурки:
- Праздники позади, но это не значит, что такая игрушка в виде звезды не может украсить дом. И вовсе не обязательно вешать ее на елку. Из нескольких таких звезд может получиться интересная гирлянда:
- Птичка-синичка может поселиться в вашем доме этой зимой. Достаточно взять нитки подходящего цвета и погрузиться в креатив:
- Эти подвески из ниток выглядят по особенному уютно и тепло:
- Отличная идея для украшения дома к Хэллоуину. А ваша семья отмечает этот праздник?
Как сделать помпоны своими руками из ниток
Помпоны из ниток — отличный мягкий материал для того, чтобы сделать коврики и пуфы, гирлянды или декоративные элементы для одежды и интерьера.
Есть несколько способов как сделать помпоны своими руками. Каждый из них очень прост. Нам понадобятся нитки, вилка, картонные круги и собственные пальцы.
Помпоны своими руками на картонных кругах
- Вырежьте из картона два одинаковых круга с отверстиями посередине. От диаметра круга зависит размер готового помпона.
- Начните наматывать пряжу на круги.
- Чтобы сделать помпон быстрее, наматывайте нить, сложенную вдвое, вчетверо или больше.
- Чем больше вы намотаете пряжи, тем более пушистым будет помпон. Затем аккуратно ножницами разрежьте нитки по бокам.
- Немного раздвиньте круги из картона и крепко завяжите ниткой посередине.
- Снимите картон, распушите помпон и при необходимости подровняйте его, придав идеальную форму.
Помпоны своими руками из ниток на пальцах
Если картона нет под рукой, то помпоны можно сделать просто на пальцах.
- Намотайте на пальцы пряжу (1).
- Можно сделать маленькие помпоны на два пальца или большие на все пять (2).
- Аккуратно снимите моток с руки и положите на стол (3).
- Отрежьте нитку и крепко завяжите узлом поперек мотка (4-5).
- Разрежьте по бокам нитки (6),
- расправьте (7),
- подровняйте ножницами форму (8).
Маленькие помпоны своими руками на вилке
Небольшие помпоны для декора удобно делать на вилке. Ход работы идентичен двум предыдущим вариантам.
Намотайте пряжу поперек зубчиков вилки, перевяжите ниткой посередине мотка, снимите с вилки и разрежьте по бокам.
Бантики
С помощью вилки можно делать небольшие декоративные бантики. Возьмите тонкую ленточку или тесьму длиной около 15 см и оберните вокруг левой стороны вилки.
Конец ленты, лежащей на задней части вилки, оберните вокруг правой стороны на переднюю часть (вторая половинка ленты остается под этой) и пропустите между средними зубьями снизу.
Переднюю половинку ленты заводим вверх также между средними зубьями. Получилось, что оба конца ленточки вышли с обратной стороны вилки сверху и снизу горизонтально натянутой ленты. Завяжите вокруг нее концы узелком.
Снимите полученный бантик с вилки, при необходимости обрежьте длинные кончики и обработайте их.
Читайте также:
Сохранить и поделиться:
Понимание потоков Java раз и навсегда | Джулиана Безерра | Запуск
Иногда нам нужно выполнить несколько задач одновременно. Компьютер может сделать это, используя Threads . Возможно, вы читаете этот пост и одновременно слушаете музыку, поскольку ваш компьютер использует потоки для запуска обоих процессов.
В программах Java потоки могут быть полезны в различных сценариях. Примером может служить ситуация, когда нам нужно обработать большие наборы данных за короткий промежуток времени.Разделение этой задачи между потоками — способ удовлетворить это требование времени. Это здорово, но как мы можем это сделать? Позвольте показать вам на практическом примере.
💡 Технические характеристики оборудования, такие как количество ядер процессора, могут влиять на производительность потоков. Если потоков больше, чем ядер, SO придется управлять временем, которое каждый процесс проводит в доступном ядре, потому что они не могут работать параллельно. Такое поведение может снизить производительность.
Сначала создадим задачи.Каждая задача будет выполняться одним потоком, представленным классом Thread:
Созданные задачи еще не назначены логике. Если вы посмотрите официальную документацию, вы заметите, что конструктор потока получает аргумент Runnable. Этот класс описывает то, что необходимо сделать, что идеально соответствует концепции задачи. Давайте создадим задачу, реализовав интерфейс Runnable:
Runnable имеет метод запуска, который содержит логику задачи. В приведенном выше примере задача выводит идентификатор потока во время своего выполнения.Давайте добавим эту задачу в наши потоки:
💡 Мы могли бы сделать PrintHelloTask extends Thread, но это было бы неправильно с точки зрения наследования, поскольку единственное поведение, которое нам нужно от задачи, — это ее способность к выполнению, которая принадлежит Runnable интерфейс. Если вы унаследованы от Thread, PrintHelloTask получает ненужное поведение для нашей задачи печати. Разделение проблем — это важная вещь в объектно-ориентированном дизайне, поэтому я рекомендую вам использовать этот шаблон при реализации ваших потоков.
Начать резьбу легко.Нам просто нужно вызвать метод start :
Метод start вызывает задачу Runnable, используемую в конструкторе Thread. Запускаем приложение и проверяем результат:
Здравствуйте, Задача 2!
Здравствуйте, Задача 3!
Здравствуйте, Задача 1!
Здравствуйте, Задача 4!
💡 Если вы выполните программу несколько раз, вы заметите что-то странное. Порядок стартовых вызовов не имеет значения, потому что потоки не выполняются последовательно! Программа сначала запустила задачу 1, но задача 2 была выполнена раньше.Это связано с тем, что потоки выполняются одновременно, поэтому мы не можем гарантировать, какой из них завершится первым.
Когда потоки работают, иногда нам нужно отслеживать их выполнение, чтобы увидеть, если что-то пойдет не так. Это можно сделать с помощью JConsole.
Во-первых, нам нужно увеличить время выполнения PrintHelloTask. Давайте сделаем это с помощью метода sleep :
Метод sleep получает в качестве аргумента время (в миллисекундах), в течение которого поток будет спать. Это означает, что наши потоки будут спать в течение 1 минуты, чтобы мы могли визуализировать их в JConsole.
Запустите программу еще раз, но теперь откройте JConsole и подключитесь к JVM нашей программы:
JConsole показывает все потоки, выполняющиеся в текущий момент:
JVM называет потоки по шаблону Thread-Index . Мы могли бы сами выбрать имена, у конструктора есть аргумент для этого, но пока давайте оставим это простым.
💡 JConsole можно найти в каталоге bin вашего JDK. Возможно, вам потребуется выполнить его с правами (sudo или администратора).
Это обычная проблема, когда потоки обращаются к одному и тому же ресурсу. Если поток изменяет ресурс до того, как его получит другой, это повлияет на результат.
Давайте посмотрим на это поведение на практическом примере. Реализуем счетчик. Этот класс будет считать числа в порядке возрастания (т. Е. 1, 2, 3, e 4). Каждый поток будет печатать число, поэтому мы должны обеспечить доступ к ресурсу по одному потоку за раз. Начальный счетчик будет похож на приведенный ниже код:
Задача просто напечатает счетчик и увеличит его:
Ключевое слово synchronize гарантирует, что все внутри блока будет выполнено только в том случае, если нет потока, выполняющего этот блок.Для этого используется мьютекс , который является ключом, блокирующим доступ к разделенному блоку (ресурсу). В нашем примере ключ — это сам объект, потому что он содержит счетчик, к которому обращаются все потоки. Мьютекс синхронизирует печать между всеми потоками, тем самым обеспечивая порядок подсчета. Мы также добавили имя потока в сообщение, напечатанное CounterTask, чтобы мы могли определить, какой поток напечатал каждое значение счетчика:
Thread-1: 1
Thread-3: 2
Thread-2: 3
Thread-4: 4
Вы можете запустить эту программу несколько раз и убедиться, что счетчик всегда печатается в правильном порядке.Что может измениться, так это последовательность потоков, потому что, как я упоминал ранее, потоки выполняются параллельно, и поэтому для них нет порядка.
Это распространенный сценарий, когда поток должен запускаться после освобождения ресурса. Блок synchronized только гарантирует, что операция выполняется атомарно, но не управляет порядком выполнения задачи. Для этого мы можем использовать метод wait , который реализован всеми java-объектами. Этот метод возвращает ключ, используемый внутри синхронизированного блока для разблокировки доступа к ресурсу, чтобы другим потокам не приходилось ждать ресурс, который им не нужен.Когда ресурс готов, мы уведомляем ожидающие потоки о продолжении их выполнения, избегая знаменитого Deadlock .
Чтобы проиллюстрировать эту проблему, представьте себе ситуацию, когда система работает в интерактивном / автономном режиме. Когда активен автономный режим, данные помечаются для синхронизации, когда система подключается к сети. Говоря о потоках, у нас будет один поток для чтения данных, а другой — для синхронизации этих данных, чтобы он стал доступен онлайн. Такое поведение требует, чтобы поток чтения шел первым и ждал синхронизирующего потока перед повторным чтением этой информации.Давайте реализуем эти потоки:
Как вы можете видеть в приведенной выше реализации, данные считываются, если они синхронизированы, что достигается методом wait . Чтобы предотвратить тупик, мы используем метод notifyAll , чтобы возобновить выполнение ожидающих потоков. Наконец, давайте создадим класс, который создает экземпляры этих потоков:
Данные сначала не синхронизированы, поэтому ожидают синхронизации, а затем читают:
Чтение данных ...
Синхронизация данных ...
Синхронизировано!
Data: 0
Что делать, если данные уже были синхронизированы? Прокомментируйте строку 4 и снова запустите программу:
Чтение данных ...
Данные: 0
Синхронизация данных ...
Что произошло? Поскольку мы попросили поток синхронизации подождать, данные перестают синхронизироваться, и это событие никогда не происходит, оно будет ждать вечно. Способ предотвратить это — сделать поток синхронизации демоном с помощью метода setDaemon :
Попробуйте выполнить его еще раз.Вы заметите, что JVM завершает поток демона синхронизации, когда другие потоки не активны.
Это очень частый вопрос! При создании потоков они выполняются независимо друг от друга. Но есть случаи, когда нам нужно их согласовать, например, в ситуациях, когда прерывание потока должно вызывать прерывание связанных потоков. Это происходит, например, когда мы закрываем программу. Все связанные задачи должны быть закрыты, чтобы они не потребляли ресурсы платформы выполнения.Имея это в виду, как мы можем это сделать, если метод finalize потоков устарел? Обычный способ сделать это — контролировать изменчивый атрибут для завершения выполнения потока в методе run. Этот атрибут всегда актуален между потоками, даже в несинхронизированных разделах.
Чтобы проиллюстрировать эту проблему, давайте рассмотрим гоночную систему. Бегуны бегут одновременно, но если один дойдет до финиша, другой может остановиться, так как проиграл. Наиболее интуитивно понятная реализация этой системы:
Выполните приведенный выше код, чтобы увидеть результат:
Запуск...
Бегун 1 бежит ...
Бегун 2 бежит ...
Победитель: Бегун 1
Победитель: Бегун 2
Очевидно оба бегуна выиграли, потому что, когда прибыл Бегун 1, Бегун 2 продолжил бежать, не зная, что гонка окончена и победителем стал «Бегун 1». Чтобы исправить это поведение, бегуны должны проверить, завершена ли гонка, чтобы в этом случае они могли остановиться. Давайте добавим эту проверку в метод run :
Атрибут гонки завершен сделан изменчивым, чтобы потоки считывали это значение последовательно.Потоки завершаются, как только завершится принимает значение true. Класс RaceMain не был изменен. Давайте попробуем бежать еще раз:
Запуск ...
Бегун 2 бежит ...
Победитель: Бегун 2
Бегун 1 бежит ...
Бегун 1 проиграл :(
Как мы видим, после того, как Бегун 2 выиграл, Бегун 1 перестал работать.
Сообщение стало большим, но оно все еще не охватывало всю тему потоков в Java. Если вы хотите углубиться, я предлагаю вам в качестве упражнения изучить официальную документацию.Несомненно, то, что вы здесь прочитали, поможет вам понять самые сложные концепции.
многопоточность — Что такое «нить» (на самом деле)?
Я собираюсь использовать много текста из книги «Концепции операционных систем» Абрахама Сильбершатца, ПИТЕРА БАЭРА ГАЛВИНА и ГРЕГА ГЭГНА вместе со своим собственным пониманием вещей.
Процесс
Любое приложение находится на компьютере в виде текста (или кода).
Мы подчеркиваем, что программа сама по себе не является процессом.Программа — это пассивный объект, такой как файл, содержащий список инструкций, хранящихся на диске (часто называемый исполняемым файлом).
Когда мы запускаем приложение, мы создаем экземпляр выполнения. Этот экземпляр выполнения называется процессом. РЕДАКТИРОВАТЬ: (Согласно моей интерпретации, аналогично классу и экземпляру класса, экземпляр класса является процессом.)
Примером процессов является Google Chrome. Когда мы запускаем Google Chrome, порождаются 3 процесса:
• Браузер Процесс отвечает за управление пользовательским интерфейсом как а также дисковый и сетевой ввод-вывод.Новый процесс браузера создается, когда Chrome запущен. Создается только один процесс браузера.
• Renderer процессы содержат логику для визуализации веб-страниц. Таким образом, они содержат логику для обработки HTML, Javascript, изображений и т. д. Как правило, для каждого веб-сайта создается новый процесс рендеринга. открыт в новой вкладке, поэтому могут быть активны несколько процессов рендеринга в то же время.
• Подключаемый модуль Процесс создается для каждого типа подключаемого модуля (например, Flash или QuickTime) уже используется.Процессы подключаемых модулей содержат код для плагин, а также дополнительный код, который позволяет плагину общаться со связанными процессами рендерера и браузером процесс.
Резьба
Чтобы ответить на этот вопрос, я думаю, вы должны сначала узнать, что такое процессор. Процессор — это аппаратное обеспечение, которое фактически выполняет вычисления. РЕДАКТИРОВАТЬ: (Вычисления, такие как добавление двух чисел, сортировка массива, в основном выполнение написанного кода)
Теперь перейдем к определению потока.
Поток — это базовая единица использования ЦП ; он состоит из идентификатора потока, программы счетчик, набор регистров и стек.
РЕДАКТИРОВАТЬ: Определение потока с веб-сайта Intel:
Поток, или поток выполнения, — это программный термин, обозначающий базовую упорядоченную последовательность инструкций, которые могут быть переданы или обработаны одним ядром ЦП.
Итак, если процесс Renderer из приложения Chrome сортирует массив чисел, сортировка будет выполняться в потоке / потоке выполнения.(Грамматика нитей меня сбивает с толку)
Моя интерпретация вещей
Процесс — это экземпляр выполнения. Потоки — это фактические рабочие, которые выполняют вычисления через доступ к ЦП. Когда для процесса выполняется несколько потоков, процесс предоставляет общую память.
РЕДАКТИРОВАТЬ: Другая информация, которую я нашел полезной, чтобы дать больше контекста
Все современные компьютеры имеют более одного потока. Количество потоков в компьютере зависит от количества ядер в компьютере.
Параллельные вычисления :
Из Википедии:
Параллельные вычисления — это форма вычислений, при которой несколько вычислений выполняются в перекрывающиеся периоды времени — одновременно — вместо того, чтобы последовательно (одно завершается до начала следующего). Это свойство системы — это может быть отдельная программа, компьютер или сеть — и существует отдельная точка выполнения или «поток управления» для каждого вычисления («процесса»).
Итак, я мог бы написать программу, которая вычисляет сумму 4 чисел:
(1 + 3) + (4 + 5)
В программе для вычисления этой суммы (которая будет одним процессом, выполняющимся в потоке выполнения) я могу выполнить ответвление другого процесса, который может выполняться в другом потоке, для вычисления (4 + 5) и возврата результата исходному процессу, в то время как исходный процесс вычисляет сумму (1 + 3).
Простой для понимания учебник
Что такое поток в Ruby?
Threads заставляют ваши программы Ruby выполнять несколько задач одновременно.
Примерно :
- Чтение нескольких файлов
- Обработка нескольких веб-запросов
- Создание нескольких подключений API
В результате использования потоков вы получите многопоточную программу Ruby, которая может выполнять задачи быстрее.
Но одно предупреждение…
В MRI (Ruby Interpreter Matz), стандартном способе запуска приложений Ruby, вы получите выгоду от потоков только при запуске приложений с привязкой к вводу / выводу .
Это ограничение существует из-за GIL (Global Interpreter Lock) .
Альтернативные интерпретаторы Ruby, такие как JRuby или Rubinius, в полной мере используют преимущества многопоточности.
Итак, что такое потоки?
Потоки — это рабочие или исполнительные единицы.
У каждого процесса есть хотя бы один поток, и вы можете создать больше по запросу.
Я знаю, что вы хотите увидеть пример кода.
Но сначала нам нужно поговорить о разнице между приложениями с привязкой к ЦП и приложениями с привязкой к вводу-выводу.
Приложения, связанные с вводом / выводом
Приложение с привязкой к вводу-выводу — это приложение, которому необходимо дождаться внешнего ресурса:
- запрос API
- база данных (результаты запроса)
- чтение с диска
Поток может решить остановиться, пока он ожидает доступности ресурса. Это означает, что другой поток может работать и делать свое дело, не тратя время на ожидание.
Одним из примеров приложения с привязкой к вводу-выводу является веб-сканер.
Для каждого запроса сканер должен ждать ответа сервера и ничего не может сделать во время ожидания.
Но если вы используете потоки…
Вы можете делать 4 запроса за раз и обрабатывать ответы по мере их возврата, что позволит вам быстрее получать страницы.
Теперь пришло время для вашего примера кода.
Создание потоков Ruby
Вы можете создать новый поток Ruby, вызвав Thread.new
.
Обязательно передайте блок с кодом, который должен выполняться этим потоком.
Thread.new {помещает "привет из потока"}
Довольно просто, правда?
Однако.
Если у вас есть следующий код, вы заметите, что из потока нет вывода:
t = Thread.new {ставит 10 ** 10} ставит "привет"
Проблема в том, что Ruby не ждет завершения потоков.
Вам нужно вызвать метод join
в вашем потоке, чтобы исправить приведенный выше код:
t = Thread.new {ставит 10 ** 10} ставит "привет" т. присоединиться
Если вы хотите создать несколько потоков, вы можете поместить их в массив и вызвать join
для каждого потока.
Пример :
потоки = [] 10 раз { thread << Thread.new {ставит 1} } thread.each (&: присоединиться)
При изучении потоков Ruby может оказаться полезной документация:
https://ruby-doc.org/core-2.5.0/Thread.html
Потоки и исключения
Если исключение происходит внутри потока, оно автоматически умирает, не останавливая вашу программу и не показывая никаких сообщений об ошибке.
Вот пример:
Нить.новый {поднять 'ад'}
В целях отладки вы можете захотеть, чтобы ваша программа останавливалась, когда происходит что-то плохое. Для этого вы можете установить следующий флаг на Thread
в значение true:
Thread.abort_on_exception = правда
Обязательно установите этот флаг, прежде чем создавать свои темы 🙂
Пулы потоков
Допустим, у вас есть сотни элементов для обработки, запуск потока для каждого из них уничтожит ваши системные ресурсы.
Это будет выглядеть примерно так:
pages_to_crawl =% w (индекс о контакте...) pages_to_crawl.each do | page | Thread.new {помещает страницу} конец
Если вы сделаете это, вы будете запускать сотни подключений к серверу, так что это, вероятно, не лучшая идея.
Одно из решений - использовать пул потоков.
Пулы потоков позволяют контролировать количество активных потоков в любой момент времени.
Вы можете построить свой собственный бассейн, но я бы не рекомендовал это. В следующем примере мы используем целлулоид, чтобы сделать это за вас.
Примечание: Целлулоид теперь не обрабатывается, но общая идея рабочих пулов все еще применима.
требуется "целлулоид" класс рабочий включают целлулоид def process_page (url) помещает URL конец конец pages_to_crawl =% w (индекс для контактных продуктов ...) worker_pool = Worker.pool (размер: 5) # Если вам нужно собрать возвращаемые значения, посмотрите "фьючерсы" pages_to_crawl.each do | page | worker_pool.process_page (страница) конец
На этот раз будут запущены только 5 потоков, и по завершении они выберут следующий элемент.
Условия гонки и другие опасности
Это может показаться очень крутым, но прежде чем вы начнете разбрасывать потоки по всему вашему коду, вы должны знать, что есть некоторые проблемы, связанные с параллельным кодом.
Например, потоки подвержены гонкам.
Состояние гонки - это когда что-то происходит не по порядку и создает беспорядок.
Другая проблема, которая может возникнуть, - это тупик. Это когда один поток имеет монопольный доступ (используя систему блокировки, например мьютекс) к какому-либо ресурсу и никогда не освобождает его, что делает его недоступным для всех других потоков.
Чтобы избежать этих проблем, лучше избегать сырых нитей и придерживаться какого-нибудь драгоценного камня, который уже позаботится о деталях за вас.
Больше драгоценных камней для резьбы
Мы уже использовали целлулоид для нашего пула потоков, но есть много других жемчужин, ориентированных на параллелизм, которые вы должны проверить:
Хорошо, надеюсь, вы кое-что узнали о Ruby thread !
Если вы нашли эту статью полезной, пожалуйста, поделитесь ею со своими друзьями, чтобы они тоже могли учиться 🙂
языков программирования - что могут делать несколько потоков, чего не может один поток?
Хотя потоки кажутся маленьким шагом от последовательных вычислений, по сути, они представляют собой огромный шаг вперед.Они отбрасывают самое главное и привлекательные свойства последовательных вычислений: понятность, предсказуемость и детерминизм. Потоки, как модель вычислений, дико недетерминированы, и работа программиста становится одной отсечения этого недетерминизма.
- Проблема с потоками (www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf).
Хотя есть некоторые преимущества в производительности, которые можно получить с помощью потоков, поскольку вы можете распределять работу по нескольким ядрам, они часто имеют отличную цену.
Одним из недостатков использования потоков, которые здесь еще не упоминались, является потеря разделения ресурсов, которую вы получаете с однопоточными пространствами процессов. Например, скажем, вы столкнулись с ошибкой сегментирования. В некоторых случаях можно исправить это в многопроцессорном приложении, просто позволив неисправному дочернему элементу умереть и возродившему новый. Так обстоит дело с бэкэндом prefork Apache. Когда один экземпляр httpd выходит из строя, худшим случаем является то, что конкретный HTTP-запрос может быть отброшен для этого процесса, но Apache порождает новый дочерний элемент и часто запрос, если он просто повторно отправлен и обслуживается.Конечным результатом является то, что Apache в целом не удаляется из-за неисправного потока.
Еще одно соображение в этом сценарии - утечки памяти. В некоторых случаях вы можете аккуратно обработать сбой потока (в UNIX возможно восстановление по некоторым конкретным сигналам - даже по segfault / fpviolation), но даже в этом случае вы могли потерять всю память, выделенную этим потоком. (malloc, новый и т. д.). Таким образом, несмотря на то, что ваш процесс может продолжаться, он со временем утекает все больше и больше памяти с каждой ошибкой / восстановлением.Опять же, есть до некоторой степени способы минимизировать это, например, использование пулов памяти Apache. Но это по-прежнему не защищает от памяти, которая могла быть выделена сторонними библиотеками, которые поток мог использовать.
И, как отмечали некоторые люди, понимание примитивов синхронизации, возможно, является самым трудным для правильного понимания. Эта проблема сама по себе - просто правильная общая логика для всего вашего кода - может стать огромной головной болью. Загадочные взаимоблокировки могут возникать в самые необычные моменты, а иногда даже до тех пор, пока ваша программа не будет запущена в производственной среде, что еще больше усложняет отладку.Добавьте к этому тот факт, что примитивы синхронизации часто сильно различаются в зависимости от платформы (Windows или POSIX), и отладка часто может быть более сложной, а также возможность возникновения состояний гонки в любое время (запуск / инициализация, время выполнения и завершение работы), программирование с помощью потоков действительно не пощадит новичков. И даже к экспертам по-прежнему мало пощады только потому, что знание потоковой передачи само по себе не уменьшает сложность в целом. Кажется, что каждая строка многопоточного кода экспоненциально увеличивает общую сложность программы, а также увеличивает вероятность появления скрытого тупика или странного состояния гонки в любое время.Также может быть очень сложно написать тестовые примеры, чтобы выявить эти вещи.
Вот почему некоторые проекты, такие как Apache и PostgreSQL, по большей части основаны на процессах. PostgreSQL запускает каждый внутренний поток в отдельном процессе. Конечно, это по-прежнему не решает проблемы синхронизации и состояния гонки, но добавляет немного защиты и в некотором смысле упрощает ситуацию.
Несколько процессов, каждый из которых запускает один поток выполнения, может быть намного лучше, чем несколько потоков, выполняемых в одном процессе.А с появлением большей части нового однорангового кода, такого как AMQP (RabbitMQ, Qpid и т. Д.) И ZeroMQ, стало намного проще разделить потоки между различными пространствами процессов и даже машинами и сетями, что значительно упростило работу. Но все же это не серебряная пуля. Есть еще сложности, с которыми нужно справиться. Вы просто перемещаете некоторые из ваших переменных из пространства процесса в сеть.
Суть в том, что решение войти в область нитей не из легких. Как только вы вступаете на эту территорию, почти мгновенно все становится более сложным, и в вашу жизнь входят совершенно новые виды проблем.Это может быть весело и круто, но это как атомная энергетика - когда что-то идет не так, все может пойти плохо и быстро. Я помню, как много лет назад проходил курс обучения критичности, и они показали фотографии некоторых ученых из Лос-Аламоса, которые играли с плутонием в лабораториях еще во время Второй мировой войны. Многие не принимали практически никаких мер предосторожности в случае облучения, и в мгновение ока - в одну яркую, безболезненную вспышку, для них все было бы кончено. Через несколько дней они были мертвы. Ричард Фейнман позже называл это «щекоткой дракона за хвост».«Вот на что может походить игра с нитками (по крайней мере, для меня). Поначалу это кажется довольно безобидным, и к тому времени, когда вас укусили, вы почесываете в затылке, как быстро все пошло не так. Но, по крайней мере, нитки победили». t убить тебя.
Жизненный цикл потока Java и состояния потоков
Поток Java может находиться в любом из следующих состояний потока в течение его жизненного цикла, то есть в новом, работающем, заблокированном, ожидающем, ожидающем по времени или завершенном. Они также называются событиями жизненного цикла потока в java.Давайте разберемся в каждом состоянии более подробно.
Состояния жизненного цикла потока Java
Новый
Как только вы создадите новый поток, он будет в состоянии
NEW
. Он остается в этом состоянии до тех пор, пока программа не запустит поток, используя его методstart ()
.На этом этапе поток неактивен, и это внутреннее состояние программирования на Java.
Runnable
Вызов метода
start ()
для потока переводит его в состояниеRUNNABLE
.На этом этапе управление выполнением передается планировщику потоков, чтобы завершить его выполнение. С этого момента планировщик потоков решает, что этот поток должен быть выполнен (также известный как диспетчеризация потока) или должен быть приостановлен, чтобы дать возможность другим запускаемым потокам.Планирование потоков зависит от платформы - поведение многопоточной программы может различаться в разных реализациях Java.
В большинстве операционных систем каждому потоку дается небольшое количество процессорного времени, называемое квантом или временным интервалом, для выполнения своей задачи.Говорят, что задача, использующая его квант, находится в состоянии
RUNNING
. Когда его квант истекает, поток возвращается в состояниеRUNNABLE
, и операционная система назначает другой поток процессору.Процесс, который операционная система использует для определения потока для отправки, называется планированием потоков и зависит от приоритетов потоков.
Операционная система скрывает состояния RUNNABLE и RUNNING от виртуальной машины Java (JVM), которая видит только состояние RUNNABLE.
Заблокирован
RUNNABLE поток переходит в состояние
BLOCKED
, когда он пытается выполнить задачу, которая не может быть завершена немедленно, и он должен временно дождаться завершения этой задачи.Например, когда поток выдает запрос ввода / вывода, операционная система блокирует выполнение потока до тех пор, пока этот запрос ввода / вывода не завершится - в этот момент заблокированный поток переходит в состояние RUNNABLE, чтобы он мог возобновить выполнение.Заблокированный поток не может использовать процессор, даже если он доступен.
Ожидание
Поток может быть переведен в состояние ожидания по разным причинам, например, вызывая это метод
wait ()
. Обычно программа переводит поток в состояние WAIT, потому что нужно сделать что-то еще до того, что делает текущий поток.Подробнее: работа с wait (), notify () и notifyAll () в Java?
После того, как состояние ожидания потока закончилось или оно закончилось, его состояние изменяется на
RUNNABLE
и возвращается обратно в пул потоков.Timed Waiting
RUNNABLE thread может перейти в состояние
TIMED WAITING
, если он предоставляет необязательный интервал ожидания, когда он ожидает, пока другой поток выполнит задачу. Вы можете поместить поток Java в состояниеTIMED WAITING
, вызвав его методsleep (long millis)
или wait (long millis) метод.Такой поток возвращается в состояние
RUNNABLE
, когда он получает уведомление от другого потока или когда истекает временной интервал - в зависимости от того, что наступит раньше.Ожидающие по времени потоки и ожидающие потоки не могут использовать процессор, даже если он доступен.
Завершено
Поток переходит в состояние
ЗАВЕРШЕН
(иногда называемое мертвым состоянием ), когда он успешно завершает свою задачу или иным образом завершается из-за какой-либо ошибки или даже был принудительно завершен.
Пожалуйста, помните, что хотя планировщик потоков JVM и ОС делает все возможное, иногда потоки могут вызывать голодание или взаимоблокировку.Это происходит, когда ожидающий поток (назовем этот поток1) не может продолжить работу, потому что он ожидает (прямо или косвенно) другого потока (назовем этот поток2) для продолжения, в то время как одновременно поток2 не может продолжить, потому что он ожидает (прямо или косвенно) для thread1, чтобы продолжить.
Удачного обучения !!
Ссылка (а):
Состояния потоков Java
Введение в многопоточность в Python - Real Python
Смотреть сейчас В этом руководстве есть связанный видеокурс, созданный командой Real Python.Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Threading in Python
Потоковая обработка Python позволяет вам запускать разные части вашей программы одновременно и может упростить ваш дизайн. Если у вас есть некоторый опыт работы с Python и вы хотите ускорить свою программу с помощью потоков, то это руководство для вас!
Из этой статьи вы узнаете:
- Какие темы
- Как создавать потоки и ждать их завершения
- Как использовать
ThreadPoolExecutor
- Как избежать состояния гонки
- Как использовать общие инструменты, которые предоставляет Python
threading
В этой статье предполагается, что вы знакомы с основами Python и используете как минимум версию 3.6 для запуска примеров. Если вам нужно освежиться, вы можете начать с Пути обучения Python и быстро освоиться.
Если вы не уверены, хотите ли вы использовать Python threading
, asyncio
или multiprocessing
, тогда вы можете проверить ускорение вашей программы Python с помощью параллелизма.
Все источники, используемые в этом руководстве, доступны вам в репозитории Real Python GitHub.
Бесплатный бонус: 5 мыслей о Python Mastery, бесплатный курс для разработчиков Python, который показывает вам дорожную карту и образ мышления, которые вам понадобятся, чтобы вывести свои навыки Python на новый уровень.
Пройдите тест: Проверьте свои знания с помощью нашей интерактивной викторины «Python Threading». По завершении вы получите оценку, чтобы вы могли отслеживать свой прогресс в обучении с течением времени:
Пройти тест »
Что такое нить?
Поток - это отдельный поток выполнения. Это означает, что в вашей программе будут происходить сразу две вещи. Но для большинства реализаций Python 3 разные потоки на самом деле не выполняются одновременно: они просто кажутся.
Заманчиво думать о многопоточности как о двух (или более) разных процессорах, работающих над вашей программой, каждый из которых одновременно выполняет независимую задачу. Это почти верно. Потоки могут выполняться на разных процессорах, но они будут выполняться только по одному.
Для одновременного выполнения нескольких задач требуется нестандартная реализация Python, написание части кода на другом языке или использование многопроцессорной обработки
, что требует дополнительных накладных расходов.
Из-за того, как работает реализация Python в CPython, многопоточность может не ускорить все задачи. Это связано с взаимодействиями с GIL, которые по существу ограничивают одновременный запуск одного потока Python.
Задачи, которые проводят большую часть своего времени в ожидании внешних событий, обычно являются хорошими кандидатами для многопоточности. Проблемы, требующие интенсивных вычислений ЦП и тратящих мало времени на ожидание внешних событий, могут вообще не выполняться быстрее.
Это верно для кода, написанного на Python и работающего в стандартной реализации CPython.Если ваши потоки написаны на C, они могут выпускать GIL и работать одновременно. Если вы используете другую реализацию Python, ознакомьтесь с документацией, чтобы узнать, как она обрабатывает потоки.
Если вы используете стандартную реализацию Python, пишете только на Python и имеете проблему, связанную с процессором, вам следует вместо этого проверить модуль multiprocessing .
Архитектура вашей программы с использованием многопоточности также может обеспечить повышение ясности проектирования.Большинство примеров, о которых вы узнаете в этом руководстве, не обязательно будут выполняться быстрее, потому что они используют потоки. Использование в них резьбы помогает сделать дизайн более понятным и понятным.
Итак, давайте прекратим говорить о потоках и начнем их использовать!
Начало темы
Теперь, когда вы получили представление о нити, давайте узнаем, как ее создать. Стандартная библиотека Python обеспечивает threading
, который содержит большинство примитивов, которые вы увидите в этой статье. Thread
в этом модуле красиво инкапсулирует потоки, обеспечивая чистый интерфейс для работы с ними.
Чтобы запустить отдельный поток, вы создаете экземпляр Thread
, а затем сообщаете ему .start ()
:
1 импортный журнал
2импорт резьбы
3время импорта
4
5def функция_потока (имя):
6 logging.info ("Тема% s: запускается", имя)
7 раз. Сон (2)
8 logging.info ("Тема% s: завершение", имя)
9
10if __name__ == "__main__":
11 format = "% (asctime) s:% (message) s"
12 лесозаготовок.basicConfig (формат = формат, уровень = logging.INFO,
13 datefmt = "% H:% M:% S")
14
15 logging.info («Главное: перед созданием потока»)
16 x = threading.Thread (цель = функция_потока, args = (1,))
17 logging.info («Главное: перед запуском потока»)
18 x.start ()
19 logging.info («Главное: дождаться завершения потока»)
20 # x.join ()
21 logging.info («Главное: все готово»)
Если вы посмотрите на операторы регистрации, вы увидите, что основной раздел
создает и запускает поток:
x = нарезание резьбы.Поток (target = thread_function, args = (1,))
x.start ()
Когда вы создаете Thread
, вы передаете ему функцию и список, содержащий аргументы этой функции. В этом случае вы указываете Thread
запустить thread_function ()
и передать ему 1
в качестве аргумента.
В этой статье вы будете использовать последовательные целые числа в качестве имен для ваших цепочек. Существует threading.get_ident ()
, который возвращает уникальное имя для каждого потока, но обычно они не короткие и легко читаемые.
thread_function ()
сам по себе мало что делает. Он просто регистрирует некоторые сообщения с time.sleep ()
между ними.
Когда вы запустите эту программу как есть (с закомментированной строкой двадцать), результат будет выглядеть так:
$ ./single_thread.py
Основное: перед созданием потока
Основной: перед запуском потока
Поток 1: начало
Main: дождитесь завершения потока
Главное: все готово
Поток 1: отделка
Вы заметите, что Thread
завершился после того, как завершился раздел Main
вашего кода.Вы вернетесь к тому, почему это так, и поговорите о таинственной двадцатой строке в следующем разделе.
Демонические потоки
В информатике, демон
- это процесс, который выполняется в фоновом режиме.
Python threading
имеет более конкретное значение для демона
. Демон поток
будет немедленно завершен, когда программа завершится. Один из способов подумать об этих определениях - рассмотреть поток демона
как поток, который работает в фоновом режиме, не беспокоясь о его завершении.
Если программа выполняет потоков
, которые не являются демонами
, то программа будет ждать завершения этих потоков, прежде чем завершиться. Потоки
, которые являются демонами, однако просто уничтожаются, где бы они ни находились, при выходе из программы.
Давайте внимательнее посмотрим на результат вашей программы выше. Последние две строчки представляют интерес. Когда вы запустите программу, вы заметите паузу (около 2 секунд) после того, как __main__
напечатал свое сообщение all done
и до того, как поток будет завершен.
Эта пауза - это Python, ожидающий завершения недемонического потока. Когда ваша программа Python завершается, частью процесса выключения является очистка подпрограммы потоковой передачи.
Если вы посмотрите на исходный код Python threading
, вы увидите, что threading._shutdown ()
проходит через все запущенные потоки и вызывает .join ()
для всех, у которых нет демона Установлен флаг
.
Итак, ваша программа ожидает выхода, потому что сам поток ожидает в спящем режиме.Как только он завершит и напечатает сообщение, .join ()
вернется, и программа сможет выйти.
Часто это именно то, что вам нужно, но у нас есть и другие варианты. Давайте сначала повторим программу с потоком демона
. Это можно сделать, изменив способ создания потока
, добавив флаг daemon = True
:
x = threading.Thread (target = thread_function, args = (1,), демон = True)
Теперь, когда вы запустите программу, вы должны увидеть следующий результат:
$./daemon_thread.py
Основное: перед созданием потока
Основной: перед запуском потока
Поток 1: начало
Main: дождитесь завершения потока
Главное: все готово
Разница в том, что последняя строка вывода отсутствует. thread_function ()
не удалось выполнить. Это был поток демона , поэтому, когда
__main__
достиг конца своего кода и программа хотела завершить работу, демон был убит.
join ()
a ПотокДемонические потоки удобны, но как насчет того, чтобы дождаться остановки потока? Как насчет того, чтобы сделать это и не выходить из программы? Теперь давайте вернемся к исходной программе и посмотрим на эту закомментированную строку двадцать:
. Чтобы указать одному потоку дождаться завершения другого потока, вы вызываете .присоединиться ()
. Если вы раскомментируете эту строку, основной поток остановится и будет ждать завершения потока x
.
Вы проверяли это на коде с потоком демона или обычным потоком? Оказывается, это неважно. Если вы .join ()
поток, этот оператор будет ждать, пока любой из типов потоков не завершится.
Работа с большим количеством потоков
Пример кода до сих пор работал только с двумя потоками: основным потоком и тем, который вы начали с потоковой передачи .Объект Thread
.
Часто возникает необходимость запустить несколько потоков, чтобы они выполняли интересную работу. Давайте начнем с более сложного способа сделать это, а затем перейдем к более легкому методу.
Более сложный способ запуска нескольких потоков - тот, который вы уже знаете:
импорт журнала
импорт потоковой передачи
время импорта
def thread_function (имя):
logging.info ("Тема% s: запускается", имя)
время сна (2)
logging.info ("Тема% s: завершение", имя)
если __name__ == "__main__":
format = "% (asctime) s:% (сообщение) s"
Ведение журнала.basicConfig (формат = формат, уровень = logging.INFO,
datefmt = "% H:% M:% S")
потоки = список ()
для индекса в диапазоне (3):
logging.info ("Main: создать и запустить поток% d.", index)
x = threading.Thread (target = thread_function, args = (индекс,))
threads.append (x)
x.start ()
для индекса поток в перечислении (потоки):
logging.info ("Main: перед присоединением к потоку% d.", index)
thread.join ()
logging.info ("Основная часть: поток% d завершен", индекс)
В этом коде используется тот же механизм, который вы видели выше, для запуска потока, создания объекта Thread
и последующего вызова .Старт ()
. Программа хранит список объектов Thread
, чтобы затем ждать их позже, используя .join ()
.
Многократный запуск этого кода, вероятно, даст интересные результаты. Вот пример вывода с моей машины:
$ ./multiple_threads.py
Основной: создать и запустить поток 0.
Поток 0: начало
Основной: создать и запустить поток 1.
Поток 1: начало
Основной: создать и запустить поток 2.
Поток 2: начало
Основной: перед присоединением к потоку 0.Поток 2: отделка
Поток 1: отделка
Поток 0: отделка
Основной: поток 0 завершен
Основной: перед присоединением к потоку 1.
Основной: поток 1 завершен
Основной: перед присоединением к потоку 2.
Основной: поток 2 выполнен
Если вы внимательно просмотрите выходные данные, вы увидите, что все три потока запускаются в ожидаемом порядке, но в этом случае они заканчиваются в обратном порядке! Несколько прогонов приведут к разному порядку. Найдите сообщение Thread x: finish
, которое сообщит вам, когда каждый поток завершен.
Порядок выполнения потоков определяется операционной системой и его довольно сложно предсказать. Это может (и, вероятно, будет) варьироваться от запуска к запуску, поэтому вам нужно знать об этом, когда вы разрабатываете алгоритмы, использующие потоки.
К счастью, Python предоставляет вам несколько примитивов, которые вы рассмотрите позже, чтобы помочь координировать потоки и заставить их работать вместе. Перед этим давайте посмотрим, как немного упростить управление группой потоков.
Использование
ThreadPoolExecutor
Есть более простой способ создать группу потоков, чем тот, который вы видели выше.Он называется ThreadPoolExecutor
и является частью стандартной библиотеки в concurrent.futures
(начиная с Python 3.2).
Самый простой способ создать его - в качестве диспетчера контекста, используя оператор с оператором
для управления созданием и уничтожением пула.
Вот __main__
из последнего примера, переписанный для использования ThreadPoolExecutor
:
импорт одновременных фьючерсов
# [остальной код]
если __name__ == "__main__":
format = "% (asctime) s:% (сообщение) s"
Ведение журнала.basicConfig (формат = формат, уровень = logging.INFO,
datefmt = "% H:% M:% S")
с concurrent.futures.ThreadPoolExecutor (max_workers = 3) в качестве исполнителя:
executeor.map (функция_потока, диапазон (3))
Код создает ThreadPoolExecutor
в качестве диспетчера контекста, сообщая ему, сколько рабочих потоков он хочет в пуле. Затем он использует .map ()
для пошагового выполнения итерации вещей, в вашем случае range (3)
, передавая каждое из них потоку в пуле.
Конец с блоком
заставляет ThreadPoolExecutor
выполнить .join ()
для каждого из потоков в пуле. Настоятельно рекомендуется использовать ThreadPoolExecutor
в качестве диспетчера контекста, когда это возможно, чтобы никогда не забыть .join ()
потоки.
Примечание: Использование ThreadPoolExecutor
может вызвать некоторые сбивающие с толку ошибки.
Например, если вы вызываете функцию, которая не принимает параметров, но передаете ей параметры в .map ()
, поток выдаст исключение.
К сожалению, ThreadPoolExecutor
скроет это исключение, и (в случае выше) программа завершится без вывода. Поначалу это может быть довольно запутанным при отладке.
При запуске исправленного кода примера будет получен следующий результат:
$ ./executor.py
Поток 0: начало
Поток 1: начало
Поток 2: начало
Поток 1: отделка
Поток 0: отделка
Поток 2: отделка
Опять же, обратите внимание, как Thread 1
завершился до Thread 0
.Планирование потоков выполняется операционной системой и не следует плану, который легко понять.
Условия гонки
Прежде чем перейти к другим функциям, скрытым в Python threading
, давайте немного поговорим об одной из наиболее сложных проблем, с которыми вы столкнетесь при написании многопоточных программ: условиях гонки.
После того, как вы увидели, что такое состояние гонки, и взглянули на то, что происходит, вы перейдете к некоторым примитивам, предоставляемым стандартной библиотекой, чтобы предотвратить возникновение состояний гонки.
Состояния состязания могут возникать, когда два или более потока обращаются к совместно используемому фрагменту данных или ресурсу. В этом примере вы собираетесь создать большое состояние гонки, которое происходит каждый раз, но имейте в виду, что большинство условий гонки не так очевидны. Часто они возникают редко и могут привести к запутанным результатам. Как вы понимаете, это затрудняет их отладку.
К счастью, это состояние гонки будет происходить каждый раз, и вы подробно рассмотрите его, чтобы объяснить, что происходит.
В этом примере вы собираетесь написать класс, который обновляет базу данных. Ладно, на самом деле у вас не будет базы данных: вы просто собираетесь подделать ее, потому что не в этом суть этой статьи.
В вашем FakeDatabase
будут методы .__ init __ ()
и .update ()
:
класс FakeDatabase:
def __init __ (сам):
self.value = 0
def update (self, name):
logging.info ("Тема% s: начало обновления", имя)
local_copy = self.значение
local_copy + = 1
time.sleep (0,1)
self.value = local_copy
logging.info ("Тема% s: завершение обновления", имя)
FakeDatabase
отслеживает одно число: . Значение
. Это будут общие данные, на которых вы увидите состояние гонки.
.__ init __ ()
просто инициализирует .value
нулевым значением. Все идет нормально.
.update ()
выглядит немного странно. Он имитирует чтение значения из базы данных, выполнение над ним некоторых вычислений, а затем запись нового значения обратно в базу данных.
В этом случае чтение из базы данных означает просто копирование .value
в локальную переменную. Вычисление заключается в том, чтобы просто добавить единицу к значению, а затем немного .sleep ()
. Наконец, он записывает значение обратно, копируя локальное значение обратно в .value
.
Вот как вы будете использовать эту FakeDatabase
:
, если __name__ == "__main__":
format = "% (asctime) s:% (сообщение) s"
logging.basicConfig (формат = формат, уровень = ведение журнала.ИНФОРМАЦИЯ,
datefmt = "% H:% M:% S")
база данных = FakeDatabase ()
logging.info («Тестирование обновления. Начальное значение% d.», database.value)
с concurrent.futures.ThreadPoolExecutor (max_workers = 2) в качестве исполнителя:
для индекса в диапазоне (2):
executeor.submit (база данных.обновление, индекс)
logging.info («Тестирование обновления. Конечное значение% d.», database.value)
Программа создает ThreadPoolExecutor
с двумя потоками, а затем вызывает .submit ()
для каждого из них, сообщая им запустить database.update ()
.
. Submit ()
имеет подпись, которая позволяет передавать как позиционные, так и именованные аргументы функции, работающей в потоке:
.submit (функция, * аргументы, ** kwargs)
В приведенном выше использовании индекс
передается в качестве первого и единственного позиционного аргумента функции database.update ()
. Позже в этой статье вы увидите, что аналогичным образом можно передавать несколько аргументов.
Поскольку каждый поток запускает .update ()
, а .update ()
добавляет единицу к .value
, можно ожидать, что database.value
будет 2
, когда он будет распечатан в конце. Но если бы это было так, вы бы не смотрели на этот пример. Если вы запустите приведенный выше код, результат будет выглядеть так:
$ ./racecond.py
Тестирование разблокированного обновления. Начальное значение 0.
Тема 0: начало обновления
Тема 1: начало обновления
Тема 0: завершение обновления
Тема 1: завершение обновления
Тестирование разблокированного обновления.Конечное значение - 1.
Вы, возможно, ожидали, что это произойдет, но давайте рассмотрим детали того, что здесь происходит на самом деле, так как это упростит понимание решения этой проблемы.
Одна нить
Прежде чем углубиться в эту проблему с двумя потоками, давайте сделаем шаг назад и немного поговорим о некоторых деталях того, как работают потоки.
Вы не будете вдаваться в подробности здесь, поскольку на данном уровне это не важно. Мы также упростим некоторые вещи, которые не будут технически точными, но дадут вам правильное представление о том, что происходит.
Когда вы указываете своему ThreadPoolExecutor
запускать каждый поток, вы сообщаете ему, какую функцию запускать и какие параметры передать ему: executor.submit (database.update, index)
.
В результате каждый из потоков в пуле будет вызывать database.update (index)
. Обратите внимание, что база данных
является ссылкой на один объект FakeDatabase
, созданный в __main__
. Вызов .update ()
для этого объекта вызывает метод экземпляра для этого объекта.
Каждый поток будет иметь ссылку на один и тот же объект FakeDatabase
, базу данных
. Каждый поток также будет иметь уникальное значение , индекс
, чтобы облегчить чтение операторов журнала:
Когда поток запускает .update ()
, он имеет свою собственную версию всех данных , локальный для функции. В случае .update ()
это local_copy
. Это определенно хорошо. В противном случае два потока, выполняющие одну и ту же функцию, всегда будут путать друг друга.Это означает, что все переменные, привязанные к функции (или локальные), являются потокобезопасными .
Теперь вы можете начать рассмотрение того, что произойдет, если вы запустите указанную выше программу с одним потоком и одним вызовом .update ()
.
На изображении ниже показано выполнение .update ()
, если выполняется только один поток. Слева показан оператор, за которым следует диаграмма, показывающая значения в local_copy
и общей базе данных .значение
:
Диаграмма построена таким образом, что время увеличивается по мере продвижения сверху вниз. Он начинается, когда создается Thread 1
, и заканчивается, когда он завершается.
При запуске потока Thread 1
значение FakeDatabase.value
равно нулю. Первая строка кода в методе local_copy = self.value
копирует нулевое значение в локальную переменную. Затем он увеличивает значение local_copy
с помощью оператора local_copy + = 1
.Вы можете увидеть, что значение .value
в потоке Thread 1
устанавливается в единицу.
Следующий вызывается time.sleep ()
, который приостанавливает текущий поток и позволяет другим потокам выполняться. Поскольку в этом примере только один поток, это не имеет никакого эффекта.
Когда Thread 1
просыпается и продолжает работу, он копирует новое значение из local_copy
в FakeDatabase.value
, а затем поток завершается. Вы можете видеть, что database.value
установлен в единицу.
Пока все хорошо. Вы запустили .update ()
один раз, а значение FakeDatabase.value
увеличилось до единицы.
Две нити
Возвращаясь к состоянию гонки, два потока будут работать одновременно, но не одновременно. У каждого из них будет своя собственная версия local_copy
, и каждый будет указывать на одну и ту же базу данных
. Именно этот общий объект базы данных будет вызывать проблемы.
Программа начинается с Поток 1
, на котором выполняется .update ()
:
Когда Thread 1
вызывает time.sleep ()
, он позволяет другому потоку начать работу. Здесь все становится интересно.
Поток 2
запускается и выполняет те же операции. Он также копирует database.value
в свой частный local_copy
, и этот общий database.value
еще не обновлен:
Когда Thread 2
наконец переходит в спящий режим, общая база данных .значение
все еще не изменено и равно нулю, и обе частные версии local_copy
имеют значение один.
Поток 1
теперь просыпается и сохраняет свою версию local_copy
, а затем завершается, давая Thread 2
последний шанс на выполнение. Поток 2
не знает, что Поток 1
выполнил и обновил database.value
, пока он спал. Он сохраняет свою версию local_copy
в базе данных .значение
, также установив его на единицу:
Два потока имеют чередующийся доступ к одному общему объекту, перезаписывая результаты друг друга. Подобные условия гонки могут возникнуть, когда один поток освобождает память или закрывает дескриптор файла до того, как другой поток завершит доступ к нему.
Почему это не глупый пример
Приведенный выше пример создан для того, чтобы гарантировать, что состояние гонки возникает каждый раз, когда вы запускаете свою программу. Поскольку операционная система может поменять поток в любое время, можно прервать такой оператор, как x = x + 1
, после того, как он прочитал значение x
, но до того, как он записал обратно увеличенное значение.
Подробности того, как это происходит, довольно интересны, но не нужны для остальной части этой статьи, поэтому не стесняйтесь пропустить этот скрытый раздел.
Приведенный выше код не так уж и прост, как вы могли подумать. Он был разработан, чтобы вызывать состояние гонки каждый раз, когда вы его запускаете, но это значительно упрощает решение, чем большинство условий гонки.
При рассмотрении условий гонки следует иметь в виду две вещи:
Даже такая операция, как
x + = 1
, требует от процессора множества шагов.Каждый из этих шагов представляет собой отдельную инструкцию для процессора.Операционная система может поменять местами поток, на котором выполняется , в любое время . Нить можно поменять местами после любой из этих небольших инструкций. Это означает, что поток можно перевести в спящий режим, чтобы позволить другому потоку работать в середине оператора Python.
Давайте рассмотрим это подробнее. В REPL ниже показана функция, которая принимает параметр и увеличивает его:
>>> >>> def inc (x):
... x + = 1
...
>>> import dis
>>> dis.dis (inc)
2 0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (1)
4 INPLACE_ADD
6 STORE_FAST 0 (x)
8 LOAD_CONST 0 (Нет)
10 RETURN_VALUE
В примере REPL используется dis
из стандартной библиотеки Python, чтобы показать более мелкие шаги, которые процессор выполняет для реализации вашей функции. Он выполняет LOAD_FAST
значения данных x
, выполняет LOAD_CONST 1
, а затем использует INPLACE_ADD
для сложения этих значений.
Мы останавливаемся здесь по особой причине. Это точка в .update ()
выше, где time.sleep ()
заставил потоки переключиться. Вполне возможно, что время от времени операционная система будет переключать потоки в этот точный момент, даже без sleep ()
, но вызов sleep ()
заставляет это происходить каждый раз.
Как вы узнали выше, операционная система может менять потоки в любое время. Вы перешли по этому списку к выписке с пометкой 4
.Если операционная система заменяет этот поток и запускает другой поток, который также изменяет x
, то, когда этот поток возобновляется, он перезапишет x
с неправильным значением.
Технически, в этом примере не будет состояния гонки, потому что x
является локальным для inc ()
. Однако он показывает, как поток может быть прерван во время одной операции Python. Тот же набор операций LOAD, MODIFY, STORE также выполняется с глобальными и общими значениями.Вы можете исследовать с помощью модуля dis
и убедиться в этом сами.
Такое состояние гонки встречается редко, но помните, что редкое событие, происходящее за миллионы итераций, может произойти. Редкость этих состояний гонки делает их намного труднее отлаживать, чем обычные ошибки.
А теперь вернемся к регулярному обучению!
Теперь, когда вы увидели состояние гонки в действии, давайте узнаем, как их решить!
Базовая синхронизация с использованием блокировки
Есть несколько способов избежать или решить условия гонки.Здесь вы не станете рассматривать их все, но некоторые из них используются часто. Начнем с Lock
.
Чтобы решить указанное выше состояние гонки, вам нужно найти способ разрешить только одному потоку за раз в раздел чтения-изменения-записи вашего кода. Самый распространенный способ сделать это в Python называется Lock
. В некоторых других языках эта же идея называется мьютексом
. Mutex происходит от MUTual Exclusion, что и делает блокировка Lock
.
A Замок
- это объект, который действует как проход через холл. Только один поток одновременно может иметь Lock
. Любой другой поток, которому требуется блокировка Lock
, должен дождаться, пока владелец блокировки Lock
откажется от него.
Основные функции для этого: .acquire ()
и .release ()
. Поток вызовет my_lock.acquire ()
, чтобы получить блокировку. Если блокировка уже удерживается, вызывающий поток будет ждать, пока она не будет снята.Здесь есть важный момент. Если один поток получит блокировку, но никогда не вернет ее, ваша программа застрянет. Подробнее об этом вы узнаете позже.
К счастью, Python Lock
также будет работать как диспетчер контекста, поэтому вы можете использовать его в операторе with
, и он автоматически освобождается, когда блок с
завершается по любой причине.
Давайте посмотрим на FakeDatabase
с добавленным блоком Lock
. Вызывающая функция остается прежней:
класс FakeDatabase:
def __init __ (сам):
себя.значение = 0
self._lock = threading.Lock ()
def locked_update (я, имя):
logging.info ("Тема% s: начало обновления", имя)
logging.debug ("Тема% s собирается заблокировать", имя)
с self._lock:
logging.debug ("Поток% s заблокирован", имя)
local_copy = self.value
local_copy + = 1
time.sleep (0,1)
self.value = local_copy
logging.debug ("Тема% s собирается снять блокировку", имя)
logging.debug ("Тема% s после выпуска", имя)
Ведение журнала.info ("Тема% s: завершение обновления", имя)
Помимо добавления набора журналов отладки, чтобы вы могли более четко видеть блокировку, большим изменением здесь является добавление элемента с именем ._lock
, который является объектом threading.Lock ()
. Этот ._lock
инициализируется в разблокированном состоянии, блокируется и освобождается с помощью оператора
.
Здесь стоит отметить, что поток, выполняющий эту функцию, будет удерживать эту блокировку Lock
до тех пор, пока полностью не завершит обновление базы данных.В данном случае это означает, что он будет удерживать блокировку Lock
, пока копирует, обновляет, спит, а затем записывает значение обратно в базу данных.
Если вы запустите эту версию с настройкой ведения журнала на уровень предупреждения, вы увидите следующее:
$ ./fixrace.py
Тестирование заблокированного обновления. Начальное значение 0.
Тема 0: начало обновления
Тема 1: начало обновления
Тема 0: завершение обновления
Тема 1: завершение обновления
Тестирование заблокированного обновления. Конечное значение - 2.
Посмотрите на это. Ваша программа наконец-то заработала!
Вы можете включить полное ведение журнала, установив уровень DEBUG
, добавив этот оператор после настройки вывода журнала в __main__
:
лесозаготовка.getLogger (). setLevel (ведение журнала.DEBUG)
Запуск этой программы с включенным ведением журнала DEBUG
выглядит так:
$ ./fixrace.py
Тестирование заблокированного обновления. Начальное значение 0.
Тема 0: начало обновления
Поток 0 собирается заблокировать
Поток 0 заблокирован
Тема 1: начало обновления
Поток 1 собирается заблокировать
Поток 0 собирается снять блокировку
Тема 0 после релиза
Тема 0: завершение обновления
Поток 1 заблокирован
Поток 1 собирается снять блокировку
Тема 1 после релиза
Тема 1: завершение обновления
Тестирование заблокированного обновления.Конечное значение - 2.
В этих выходных данных вы можете видеть, что Thread 0
получает блокировку и все еще удерживает ее, когда переходит в спящий режим. Затем запускается поток 1
и пытается получить ту же блокировку. Поскольку поток Thread 0
все еще удерживает его, поток Thread 1
должен ждать. Это взаимное исключение, которое обеспечивает замок Lock
.
Многие примеры в оставшейся части этой статьи будут иметь ведение журнала уровня WARNING
и DEBUG
.Обычно мы будем показывать только выход уровня WARNING
, поскольку журналы DEBUG
могут быть довольно длинными. Попробуйте программы с включенной регистрацией и посмотрите, что они делают.
Тупик
Прежде чем двигаться дальше, вам следует рассмотреть типичную проблему при использовании Locks
. Как вы видели, если Lock
уже был получен, второй вызов .acquire ()
будет ждать, пока поток, который удерживает Lock
, не вызовет .выпуск ()
. Как вы думаете, что происходит, когда вы запускаете этот код:
импортная резьба
l = threading.Lock ()
print ("перед первым приобретением")
l.acquire ()
print ("перед вторым приобретением")
l.acquire ()
print ("дважды полученная блокировка")
Когда программа вызывает l.acquire ()
второй раз, она зависает в ожидании снятия блокировки Lock
. В этом примере вы можете исправить тупик, удалив второй вызов, но тупиковые ситуации обычно возникают из-за одной из двух тонких вещей:
- Ошибка реализации, при которой блокировка
- Проблема проектирования, при которой служебная функция должна вызываться функциями, которые могут иметь или не иметь уже блокировку
Первая ситуация случается иногда, но использование блокировки
в качестве диспетчера контекста значительно снижает частоту.По возможности рекомендуется писать код для использования диспетчеров контекста, поскольку они помогают избежать ситуаций, когда исключение пропускает вас через вызов .release ()
.
Проблема дизайна может быть немного сложнее на некоторых языках. К счастью, потоки Python имеют второй объект, называемый RLock
, который разработан как раз для этой ситуации. Это позволяет потоку несколько раз выполнить .acquire ()
и RLock
, прежде чем он вызовет .release ()
.Этот поток по-прежнему должен вызывать .release ()
столько же раз, сколько он вызывал .acquire ()
, но он все равно должен это делать.
Lock
и RLock
- два основных инструмента, используемых в многопоточном программировании для предотвращения состояний гонки. Есть несколько других, которые работают по-разному. Прежде чем вы посмотрите на них, давайте перейдем к немного другой проблемной области.
Продюсер-потребитель
Проблема "производитель-потребитель" - это стандартная задача в области компьютерных наук, используемая для рассмотрения проблем многопоточности или синхронизации процессов.Вы рассмотрите его вариант, чтобы получить некоторое представление о том, какие примитивы предоставляет модуль Python threading
.
В этом примере вы представите программу, которой нужно читать сообщения из сети и записывать их на диск. Программа не запрашивает сообщение, когда хочет. Он должен прослушивать и принимать сообщения по мере их поступления. Сообщения не будут приходить в обычном темпе, а будут приходить пакетами. Эта часть программы называется продюсер.
С другой стороны, если у вас есть сообщение, вам нужно записать его в базу данных. Доступ к базе данных медленный, но достаточно быстрый, чтобы не отставать от среднего темпа сообщений. Это , а не , достаточно быстро, чтобы успевать за пакетом сообщений. Эта часть является потребителем.
Между производителем и потребителем вы создадите конвейер
, который будет изменяться по мере того, как вы узнаете о различных объектах синхронизации.
Это базовая схема.Давайте посмотрим на решение, использующее Lock
. Он работает не идеально, но в нем используются инструменты, которые вы уже знаете, так что это хорошее место для начала.
Производитель-Потребитель, использующий замок
Поскольку это статья о Python threading
, и поскольку вы только что прочитали о примитиве Lock
, давайте попробуем решить эту проблему с двумя потоками, используя Lock
или два.
Общая схема заключается в том, что существует поток производителя
, который читает из поддельной сети и помещает сообщение в конвейер
:
импорт случайный
SENTINEL = объект ()
def производитель (конвейер):
"" "Представьте, что мы получаем сообщение из сети."" "
для индекса в диапазоне (10):
сообщение = random.randint (1, 101)
logging.info ("Производитель получил сообщение:% s", сообщение)
pipeline.set_message (сообщение, "Производитель")
# Отправьте дозорное сообщение, чтобы сообщить потребителю, что мы закончили
pipeline.set_message (SENTINEL, "Производитель")
Чтобы сгенерировать фальшивое сообщение, производитель
получает случайное число от единицы до ста. Он вызывает .set_message ()
на конвейере
, чтобы отправить его потребителю
.
Производитель
также использует значение SENTINEL
, чтобы сигнализировать потребителю о необходимости остановиться после того, как он отправил десять значений. Это немного неудобно, но не волнуйтесь, вы увидите способы избавиться от этого значения SENTINEL
после того, как проработаете этот пример.
По другую сторону трубопровода
находится потребитель:
def потребитель (конвейер):
"" "Представьте, что мы сохраняем число в базе данных." ""
сообщение = 0
пока сообщение не SENTINEL:
сообщение = конвейер.get_message ("Потребитель")
если сообщение не SENTINEL:
logging.info ("Сообщение, хранящееся у потребителя:% s", сообщение)
Потребитель
считывает сообщение из конвейера
и записывает его в поддельную базу данных, которая в данном случае просто выводит его на дисплей. Если он получает значение SENTINEL
, он возвращается из функции, которая завершает поток.
Прежде чем вы посмотрите на действительно интересную часть, конвейер
, вот раздел __main__
, который порождает следующие потоки:
, если __name__ == "__main__":
format = "% (asctime) s:% (сообщение) s"
Ведение журнала.basicConfig (формат = формат, уровень = logging.INFO,
datefmt = "% H:% M:% S")
# logging.getLogger (). setLevel (logging.DEBUG)
pipeline = Трубопровод ()
с concurrent.futures.ThreadPoolExecutor (max_workers = 2) в качестве исполнителя:
executeor.submit (продюсер, конвейер)
executeor.submit (потребитель, конвейер)
Это должно выглядеть довольно знакомо, поскольку оно близко к коду __main__
в предыдущих примерах.
Помните, что вы можете включить ведение журнала DEBUG
, чтобы увидеть все сообщения журнала, раскомментировав эту строку:
# лог.getLogger (). setLevel (ведение журнала.DEBUG)
Может быть полезно просмотреть сообщения журнала DEBUG
, чтобы точно увидеть, где каждый поток получает и снимает блокировки.
Теперь давайте взглянем на конвейер
, который передает сообщения от производителя
потребителю
:
класс Трубопровод:
"" "
Класс, обеспечивающий единый конвейер между производителем и потребителем.
"" "
def __init __ (сам):
себя.сообщение = 0
self.producer_lock = threading.Lock ()
self.consumer_lock = threading.Lock ()
self.consumer_lock.acquire ()
def get_message (я, имя):
logging.debug ("% s: собирается получить блокировку", имя)
self.consumer_lock.acquire ()
logging.debug ("% s: есть getlock", имя)
message = self.message
logging.debug ("% s: собирается выпустить сетлок", имя)
self.producer_lock.release ()
logging.debug ("% s: setlock выпущен", имя)
ответное сообщение
def set_message (я, сообщение, имя):
Ведение журнала.debug ("% s: собирается получить setlock", имя)
self.producer_lock.acquire ()
logging.debug ("% s: есть setlock", имя)
self.message = сообщение
logging.debug ("% s: собирается выпустить блокировку", имя)
self.consumer_lock.release ()
logging.debug ("% s: getlock выпущен", имя)
Вау! Это много кода. Довольно большой процент из них - это просто записи в журнал, чтобы было легче увидеть, что происходит, когда вы их запускаете. Вот тот же код со всеми удаленными операторами журнала:
класс Трубопровод:
"" "
Класс, обеспечивающий единый конвейер между производителем и потребителем."" "
def __init __ (сам):
self.message = 0
self.producer_lock = threading.Lock ()
self.consumer_lock = threading.Lock ()
self.consumer_lock.acquire ()
def get_message (я, имя):
self.consumer_lock.acquire ()
message = self.message
self.producer_lock.release ()
ответное сообщение
def set_message (я, сообщение, имя):
self.producer_lock.acquire ()
self.message = сообщение
self.consumer_lock.release ()
Это кажется немного более управляемым.Конвейер
в этой версии вашего кода состоит из трех членов:
-
.message
сохраняет передаваемое сообщение. -
.producer_lock
- объектthreading.Lock
, который ограничивает доступ к сообщению для потока производителя.
-
.consumer_lock
также является потоком. Блокировка
, которая ограничивает доступ к сообщению потоком потребителя.
__init __ ()
инициализирует эти три члена, а затем вызывает .acquire ()
на .consumer_lock
. Это состояние, в котором вы хотите начать. Производителю
разрешено добавлять новое сообщение, но потребителю необходимо дождаться появления сообщения.
.get_message ()
и .set_messages ()
почти противоположны. .get_message ()
вызывает .acquire ()
для блока consumer_lock
.Это вызов, который заставит потребителя
ждать, пока сообщение не будет готово.
Как только потребитель
получил .consumer_lock
, он копирует значение из .message
и затем вызывает .release ()
на .producer_lock
. Снятие этой блокировки позволяет производителю
вставить следующее сообщение в конвейер
.
Прежде чем перейти к .set_message ()
, в происходит кое-что тонкое.get_message ()
, который довольно легко пропустить. Может показаться заманчивым избавиться от сообщения
и просто завершить функцию с помощью return self.message
. Посмотрите, сможете ли вы понять, почему вы не хотите этого делать, прежде чем двигаться дальше.
Вот ответ. Как только потребитель
вызовет .producer_lock.release ()
, он может быть заменен, и производитель
может начать работу. Это могло произойти до того, как .release ()
вернется! Это означает, что существует небольшая вероятность того, что, когда функция вернет self.сообщение
, которое на самом деле может быть сгенерированным следующим сообщением , поэтому вы потеряете первое сообщение. Это еще один пример состояния гонки.
Переходя к .set_message ()
, вы можете увидеть противоположную сторону транзакции. Производитель
вызовет это с сообщением. Он получит .producer_lock
, установит .message
и вызовет .release ()
на consumer_lock
, что позволит потребителю
прочитать это значение.
Давайте запустим код, в котором для ведения журнала установлено значение WARNING
, и посмотрим, как он выглядит:
$ ./prodcom_lock.py
Производитель получил данные 43
Производитель получил данные 45
Потребительские данные хранения: 43
Производитель получил данные 86
Потребительские данные хранения: 45
Производитель получил данные 40
Потребительские данные хранения: 86
Производитель получил данные 62
Потребительские данные хранения: 40
Производитель получил данные 15
Потребительские данные хранения: 62
Производитель получил данные 16
Потребительские данные хранения: 15
Производитель получил данные 61
Потребительские данные хранения: 16
Производитель получил данные 73
Потребительские данные хранения: 61
Производитель получил данные 22
Потребительские данные хранения: 73
Потребительские данные хранения: 22
Сначала вам может показаться странным, что производитель получает два сообщения до того, как потребитель запустится.Если вы посмотрите на производителя
и .set_message ()
, вы заметите, что единственное место, где он будет ждать блокировки Lock
, - это когда он пытается поместить сообщение в конвейер. Это делается после того, как производитель
получает сообщение и регистрирует его.
Когда производитель
пытается отправить это второе сообщение, он вызывает .set_message ()
второй раз и блокируется.
Операционная система может поменять местами потоки в любое время, но обычно позволяет каждому потоку иметь разумное количество времени для выполнения перед его заменой.Вот почему производитель
обычно работает до тех пор, пока не заблокирует второй вызов .set_message ()
.
Однако, как только поток заблокирован, операционная система всегда заменяет его и находит другой поток для выполнения. В этом случае единственный другой поток, которому нужно что-то делать, - это потребитель
.
Потребитель
вызывает .get_message ()
, который читает сообщение и вызывает .release ()
на .producer_lock
, тем самым позволяя производителю
снова запускаться при следующей смене потоков.
Обратите внимание, что первое сообщение было 43
, и это именно то, что прочитал потребитель
, хотя производитель
уже сгенерировал сообщение 45
.
Хотя это и работает для этого ограниченного теста, это не лучшее решение проблемы производителя-потребителя в целом, потому что оно допускает только одно значение в конвейере за раз. Когда производитель
получит пачку сообщений, ему некуда будет их разместить.
Давайте перейдем к лучшему способу решения этой проблемы, используя очередь
.
Производитель-Потребитель, использующий очередь
Если вы хотите иметь возможность обрабатывать более одного значения в конвейере одновременно, вам понадобится структура данных для конвейера, которая позволяет этому числу увеличиваться и уменьшаться при резервном копировании данных от производителя
.
Python имеет модуль очереди
, который, в свою очередь, имеет класс Queue
. Давайте изменим конвейер
, чтобы использовать очередь
вместо простой переменной, защищенной блокировкой Lock
.Вы также будете использовать другой способ остановки рабочих потоков, используя другой примитив из Python threading
, событие
.
Начнем с события , события
. Объект threading.Event
позволяет одному потоку сигнализировать о событии
, в то время как многие другие потоки могут ожидать, когда произойдет это событие
. Ключевое использование в этом коде заключается в том, что потокам, ожидающим события, не обязательно останавливать то, что они делают, они могут просто время от времени проверять состояние Event
.
Срабатывание события может происходить по многим причинам. В этом примере основной поток просто некоторое время будет спать, а затем .set ()
it:
1if __name__ == "__main__":
2 format = "% (asctime) s:% (message) s"
3 logging.basicConfig (формат = формат, уровень = logging.INFO,
4 datefmt = "% H:% M:% S")
5 # logging.getLogger (). SetLevel (logging.DEBUG)
6
7 pipeline = Трубопровод ()
8 событие = threading.Event ()
9 с одновременным будущим.ThreadPoolExecutor (max_workers = 2) в качестве исполнителя:
10 executor.submit (продюсер, конвейер, событие)
11 executor.submit (потребитель, конвейер, событие)
12
13 time.sleep (0,1)
14 logging.info («Главное: собираюсь установить событие»)
15 event.set ()
Единственными изменениями здесь являются создание объекта event
в строке 6, передача события
в качестве параметра в строках 8 и 9, и последний раздел в строках с 11 по 13, которые спят на секунду, регистрируют сообщение, а затем позвоните по номеру .set ()
по событию.
Производитель
тоже не пришлось сильно менять:
1def производитель (конвейер, событие):
2 "" "Представьте, что мы получаем номер из сети." ""
3, пока не event.is_set ():
4 сообщение = random.randint (1, 101)
5 logging.info ("Производитель получил сообщение:% s", сообщение)
6 pipeline.set_message (сообщение, «Производитель»)
7
8 logging.info («Производитель получил событие EXIT. Выход»)
Теперь он будет зацикливаться, пока не увидит, что событие было установлено в строке 3.Он также больше не помещает значение SENTINEL
в конвейер
.
Потребитель
пришлось поменять еще немного:
Потребитель 1def (конвейер, событие):
2 "" "Представьте, что мы сохраняем число в базе данных." ""
3, пока не event.is_set () или не pipeline.empty ():
4 message = pipeline.get_message («Потребитель»)
5 logging.info (
6 "Сохранение сообщения потребителем:% s (размер очереди =% s)",
7 сообщение,
8 трубопровод.qsize (),
9)
10
11 logging.info («Потребитель получил событие EXIT. Выход»)
Хотя вам нужно извлечь код, связанный со значением SENTINEL
, вам нужно было выполнить несколько более сложное условие и
. Он не только выполняет цикл до тех пор, пока не будет установлено событие
, но также должен продолжать цикл до тех пор, пока конвейер
не будет опустошен.
Проверка того, что очередь пуста до того, как потребитель закончит, предотвращает еще одну забавную проблему.Если потребитель
действительно выходит, в то время как конвейер
содержит сообщения, могут произойти две неприятные вещи. Во-первых, вы теряете эти последние сообщения, но более серьезным является то, что производитель
может быть пойман на попытке добавить сообщение в полную очередь и никогда не вернуться.
Это происходит, если событие
запускается после того, как производитель
проверил условие .is_set ()
, но до того, как он вызовет конвейер .set_message ()
.
Если это произойдет, производитель может проснуться и выйти с полностью заполненной очередью. Затем поставщик
вызовет .set_message ()
, который будет ждать, пока в очереди не появится место для нового сообщения. Потребитель
уже вышел, поэтому этого не произойдет, и производитель не выйдет.
Остальной потребитель
должен выглядеть знакомо.
Однако конвейер
кардинально изменился:
Конвейер 1 класса (очередь.Очередь):
2 def __init __ (сам):
3 super () .__ init __ (maxsize = 10)
4
5 def get_message (я, имя):
6 logging.debug ("% s: собирается из очереди", имя)
7 значение = self.get ()
8 logging.debug ("% s: получено% d из очереди", имя, значение)
9 возвращаемое значение
10
11 def set_message (я, значение, имя):
12 logging.debug («% s: собирается добавить% d в очередь», имя, значение)
13 self.put (значение)
14 logging.debug ("% s: добавлено% d в очередь", имя, значение)
Вы можете видеть, что конвейер
является подклассом очереди .Очередь
. Очередь
имеет необязательный параметр при инициализации, чтобы указать максимальный размер очереди.
Если вы дадите положительное число для maxsize
, это ограничит очередь этим количеством элементов, в результате чего .put ()
будет блокироваться до тех пор, пока не останется менее maxsize
элементов. Если вы не укажете maxsize
, очередь будет увеличиваться до пределов памяти вашего компьютера.
.get_message ()
и .set_message ()
стал намного меньше. Они в основном оборачивают .get ()
и .put ()
в очередь
. Вам может быть интересно, куда делся весь код блокировки, который не позволяет потокам вызывать состояния гонки.
Основные разработчики, написавшие стандартную библиотеку, знали, что очередь
часто используется в многопоточных средах, и включали весь этот код блокировки внутри самой очереди
. Очередь
является потокобезопасной.
Запуск этой программы выглядит следующим образом:
$ ./prodcom_queue.py
Продюсер получил сообщение: 32
Продюсер получил сообщение: 51
Продюсер получил сообщение: 25
Продюсер получил сообщение: 94
Продюсер получил сообщение: 29
Сообщение потребителя, сохраняющее: 32 (размер очереди = 3)
Продюсер получил сообщение: 96
Сообщение потребителя, сохраняющее: 51 (размер очереди = 3)
Продюсер получил сообщение: 6
Сообщение потребителя, сохраняющее: 25 (размер очереди = 3)
Продюсер получил сообщение: 31
[удалено много строк]
Продюсер получил сообщение: 80
Сообщение потребителя, сохраняющее: 94 (размер очереди = 6)
Продюсер получил сообщение: 33
Сообщение потребителя, сохраняющее: 20 (размер очереди = 6)
Продюсер получил сообщение: 48
Сообщение потребителя, сохраняющее: 31 (размер очереди = 6)
Продюсер получил сообщение: 52
Сообщение потребителя, сохраняющее: 98 (размер очереди = 6)
Main: собираюсь назначить событие
Продюсер получил сообщение: 13
Сообщение потребителя, сохраняющее: 59 (размер очереди = 6)
Продюсер получил событие EXIT.Выход
Сообщение потребителя, сохраняющее: 75 (размер очереди = 6)
Сообщение, хранящееся у потребителя: 97 (размер очереди = 5)
Сообщение, сохраняющее потребителя: 80 (размер очереди = 4)
Сообщение потребителя, сохраняющее: 33 (размер очереди = 3)
Сообщение потребителя, сохраняющее: 48 (размер очереди = 2)
Сообщение потребителя, сохраняющее: 52 (размер очереди = 1)
Сообщение, хранящееся у потребителя: 13 (размер очереди = 0)
Потребитель получил событие EXIT. Выход
Если вы прочитаете вывод в моем примере, то увидите, что происходит кое-что интересное. Справа вверху вы можете видеть, что производитель
должен создать пять сообщений и поместить четыре из них в очередь.Операционная система заменила его, прежде чем он смог разместить пятый.
Потребитель
затем запустил и снял первое сообщение. Он распечатал это сообщение, а также то, насколько глубока была очередь на тот момент:
Сохранение сообщения потребителя: 32 (размер очереди = 3)
Вот как вы узнаете, что пятое сообщение еще не попало в конвейер
. Очередь уменьшается до трех после удаления одного сообщения. Вы также знаете, что очередь
может содержать десять сообщений, поэтому поток производителя
не был заблокирован очередью
.Он был заменен ОС.
Примечание: Ваш результат будет другим. Ваш результат будет меняться от запуска к запуску. Это самая интересная часть работы с потоками!
Когда программа начинает завершаться, вы можете видеть, что основной поток генерирует событие
, которое вызывает немедленный выход производителя
. У потребителя
еще есть над чем поработать, поэтому он продолжает работать, пока не очистит конвейер
.
Попробуйте поиграть с разными размерами очереди и звонками на время .sleep ()
в производителе
или потребителе
для имитации более длительного времени доступа к сети или к диску соответственно. Даже незначительные изменения этих элементов программы сильно повлияют на ваши результаты.
Это гораздо лучшее решение проблемы производителя и потребителя, но вы можете упростить его еще больше. Pipeline
действительно не нужен для решения этой проблемы. Как только вы уберете логирование, оно превратится в очередь . Очередь
.
Вот как выглядит окончательный код с использованием очереди .Очередь
напрямую:
импорт одновременных фьючерсов
импорт журнала
очередь импорта
случайный импорт
импорт потоковой передачи
время импорта
производитель def (очередь, событие):
"" "Представьте, что мы получаем номер из сети." ""
пока не event.is_set ():
сообщение = random.randint (1, 101)
logging.info ("Производитель получил сообщение:% s", сообщение)
queue.put (сообщение)
logging.info ("Производитель получил событие. Выходит")
def потребитель (очередь, событие):
"" "Представьте, что мы сохраняем число в базе данных."" "
пока не event.is_set () или не queue.empty ():
сообщение = queue.get ()
logging.info (
"Сохранение сообщения потребителем:% s (size =% d)", message, queue.qsize ()
)
logging.info («Потребитель получил событие. Выходит»)
если __name__ == "__main__":
format = "% (asctime) s:% (сообщение) s"
logging.basicConfig (формат = формат, уровень = logging.INFO,
datefmt = "% H:% M:% S")
pipeline = queue.Queue (maxsize = 10)
событие = threading.Event ()
с одновременным.futures.ThreadPoolExecutor (max_workers = 2) в качестве исполнителя:
executeor.submit (продюсер, конвейер, событие)
executeor.submit (потребитель, конвейер, событие)
time.sleep (0,1)
logging.info («Главное: собираюсь установить событие»)
event.set ()
Это легче читать и показывает, как использование встроенных примитивов Python может упростить сложную проблему.
Lock
и Queue
- удобные классы для решения проблем параллелизма, но есть и другие классы, предоставляемые стандартной библиотекой.Прежде чем завершить это руководство, давайте кратко рассмотрим некоторые из них.
Поток объектов
Есть еще несколько примитивов, предлагаемых модулем Python threading
. Хотя в приведенных выше примерах они вам не понадобились, они могут пригодиться в разных сценариях использования, поэтому хорошо с ними ознакомиться.
Семафор
Первый объект Python threading
, на который нужно обратить внимание, - это threading.Semaphore
. Семафор
- это счетчик с несколькими специальными свойствами.Во-первых, счет атомный. Это означает, что есть гарантия, что операционная система не заменит поток во время увеличения или уменьшения счетчика.
Внутренний счетчик увеличивается при вызове .release ()
и уменьшается при вызове .acquire ()
.
Следующее особое свойство состоит в том, что если поток вызывает .acquire ()
, когда счетчик равен нулю, этот поток будет блокироваться до тех пор, пока другой поток не вызовет .release ()
и увеличивает счетчик до единицы.
Семафоры часто используются для защиты ресурса с ограниченной емкостью. Например, у вас есть пул подключений и вы хотите ограничить размер этого пула определенным числом.
Таймер
A threading.Timer
- это способ запланировать вызов функции по прошествии определенного времени. Вы создаете таймер
, передав количество секунд ожидания и функцию для вызова:
t = нарезание резьбы.Таймер (30.0, my_function)
Вы запускаете таймер
, вызывая .start ()
. Функция будет вызываться в новом потоке в какой-то момент по истечении указанного времени, но имейте в виду, что нет никаких обещаний, что она будет вызвана точно в то время, которое вы хотите.
Если вы хотите остановить таймер
, который вы уже запустили, вы можете отменить его, вызвав .cancel ()
. Вызов .cancel ()
после срабатывания таймера Timer
ничего не делает и не вызывает исключения.
Таймер
может использоваться для подсказки пользователю действия по прошествии определенного времени. Если пользователь выполняет действие до истечения таймера Timer
, можно вызвать .cancel ()
.
Барьер
A threading. Barrier
может использоваться для синхронизации фиксированного количества потоков. При создании Barrier
вызывающий должен указать, сколько потоков будет синхронизироваться на нем. Каждый поток вызывает .wait ()
на Barrier
.Все они будут оставаться заблокированными до тех пор, пока не будет ожидать указанное количество потоков, а затем все они будут освобождены одновременно.
Помните, что потоки планируются операционной системой, поэтому, даже если все потоки освобождаются одновременно, они будут запускаться по одному за раз.
Одно из применений Barrier
- позволить пулу потоков инициализироваться. Если потоки ждут на барьере Barrier
после их инициализации, это гарантирует, что ни один из потоков не запустится до того, как все потоки завершат свою инициализацию.
Заключение: многопоточность в Python
Теперь вы многое узнали из того, что может предложить Python threading
, а также несколько примеров того, как создавать многопоточные программы и проблемы, которые они решают. Вы также видели несколько примеров проблем, возникающих при написании и отладке многопоточных программ.
Если вы хотите изучить другие варианты параллелизма в Python, ознакомьтесь с разделом «Ускорьте выполнение программы Python с помощью параллелизма».
Если вы хотите углубиться в модуль asyncio
, прочтите Async IO in Python: A Complete Walkthrough.
Что бы вы ни делали, теперь у вас есть информация и уверенность, необходимые для написания программ с использованием потоковой передачи Python!
Особая благодарность читателю Дж. Л. Диасу за помощь в наведении порядка во введении.
Пройдите тест: Проверьте свои знания с помощью нашей интерактивной викторины «Python Threading». По завершении вы получите оценку, чтобы вы могли отслеживать свой прогресс в обучении с течением времени:
Пройти тест »
Смотреть сейчас В этом руководстве есть связанный видеокурс, созданный командой Real Python.Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Threading in Python
Используйте темы для организации обсуждений
От каналов до поиска, узнайте, как работает Slack сверху вниз.
NextPrevious
Действия, активность, журналы доступа, специальные возможности, добавить, добавить приложение, добавить участников, добавить в Slack, администраторы, все пароли, аналитика, android, объявление, объявления, каталог приложений, значок приложения, Apple Watch, утверждение приложения, архив, Asana, Atlassian, приложения автоматизации, значок, сведения о выставлении счетов, биллинг, Bitbucket, пользователь-бот, поле, просмотр, звонки, вызовы:, отмена, изменения, каналы, канал мгновенно, управление каналами, уведомление о канале, предложения каналов, домены заявок, закрытие, культура компании, экспорт соответствия, составление, компьютеры, разговоры, преобразование, подключение, подключенные учетные записи, подключение, подключение, копирование сообщений, создание, настройка, настройка, пользовательский SAML, пользовательский, группы поддержки клиентов, экспорт данных, данные безопасность, деактивация, каналы по умолчанию, удаление, удаление, развертывание Slack, рабочий стол, прямые сообщения, каталог, отключение, обнаружение и присоединение, API обнаружения, отображаемое имя, DM, режим «Не беспокоить», домен, домены, понижение версии, Dropbox, дублирующиеся учетные записи, редактировать, редактирование, образование, адрес электронной почты, электронная почта, эмодзи, смайлики, Enterp рост Grid, управление мобильностью предприятия, руководители, экспорт, неудачные платежи, справедливое выставление счетов, часто задаваемые вопросы, поиск, форматирование, форматирование, структура для приложений, бесплатные пробные версии, общие, начало работы, giphy, интеграция с github, организация github, github, глоссарий, google приложения, календарь Google, диск Google, гости, основные моменты, hipchat, человеческие ресурсы, IFTTT, импорт, входящие веб-перехватчики, интеграции, ios, приглашение, ИТ-команды, JIRA, присоединиться, Продолжать, раскладка клавиатуры, сочетания клавиш, доступ к связке ключей, ключевое слово уведомления, язык, языки, оставить, предварительный просмотр ссылок, загрузка, ограничения, ссылки, linux, mac, управление рабочей областью, управление приложениями, управление участниками, маркетинг, упоминание, объединение, действия с сообщениями, отображение сообщений, отображение сообщений, продукты Microsoft, мобильный, мобильный push, перемещение каналов, перемещение рабочих пространств, несколько, отключение звука, имя, имена, шум, некоммерческие организации, уведомление, OneDrive, на борту, владельцы, пароль, оплата, платежи, разрешения, телефоны, PIN-код, план, планы, плюс план, опросы, основное право собственности, политика конфиденциальности, расстановка приоритетов задач, частный, частный канал, личные заметки и файлы, управление проектом элемент, общедоступный канал, цель, быстрое переключение, цитата, реактивация, чтение, набор, информация о реферере, напоминание, удаление, переименование, сохранение, запрос новой рабочей области, роль, роли, RSS, продажи, Salesforce, SAML, SCIM, подготовка SCIM , программа чтения с экрана, поиск, отправка, продолжительность сеанса, совместное использование сообщений, общий доступ, общий канал, общие каналы, боковая панель, вход, выход, режим регистрации, единый вход, Slack Day, Slack для команд, уведомления Slack, сохранение заметок и файлы, соглашения об уровне обслуживания, ServiceNow, подписка, статус резервной копии, slackbot, команды косой черты, фрагмент, отложенный сигнал, разработчики программного обеспечения, звездочка, статистика, шаг, синхронизация, планшеты, налог, темы, часовой пояс, советы, списки дел , тема, каналы сортировки, условия обслуживания, Trello, устранение неполадок, получение неполадок, тур, твиттер, двухфакторная аутентификация, непрочитанные сообщения, обновления, обновление, загрузка, имя пользователя, группы пользователей, URL-адрес, отпуск, поставщик и денежный перевод, видео, голосовой вызов, голос, что есть, что важно, белый список, windows phone, windows, работа в, приложения рабочего пространства, запросы на создание рабочего пространства, обнаружение рабочего пространства, рабочее пространство настройки, wunderlist, ваши действия, Zapier, масштабирование, функции, # общие, хранилище файлов, сообщения, темный режим, тема, Workflow Builder, голос, видео, совместное использование экрана, рабочие процессы, календарь Outlook, приглашенные участники, передача права собственности, белый список, предприятие Управление ключами, Безопасность на транспортном уровне, Надежная аутентификация клиентов, CSV, текстовый файл, часы работы,
Найдите «[термин]» См. [N] + другие результаты →
Начать обсуждение из любого сообщения для организации обсуждений внутри каналов и прямые сообщения (DM).Темы позволяют подробно обсуждать темы, не загромождая главное окно беседы, и упрощают отслеживание обсуждений.
Чего ожидать
- Темы связаны с исходным сообщением. Ответы не отображаются в главном окне беседы.
- Вы можете подписаться на ветку в любом канале, в котором вы участвуете, чтобы следить за обсуждением.
- О новых ответах будут уведомлены только те, кто участвовал в обсуждении или подписался на него. Использование упоминания @here или @channel в беседе не приведет к уведомлению участников беседы.
Настольный
iOS
Android
- Наведите указатель мыши на сообщение, на которое хотите ответить.
- Щелкните значок Ответить в ветке .
- Введите свой ответ.
- Отправьте ваше сообщение.
- Нажмите на сообщение, на которое хотите ответить.
- Коснитесь Начать цепочку значок или коснитесь поля Добавить ответ , чтобы добавить в существующую цепочку.
- Введите свой ответ.
- Нажмите значок бумажного самолетика , чтобы отправить сообщение.
- Нажмите на сообщение, на которое хотите ответить.
- Коснитесь Значок запуска цепочки или коснитесь поля Добавить ответ , чтобы добавить в существующую цепочку.
- Введите свой ответ.
- Нажмите значок бумажного самолетика , чтобы отправить сообщение.
Совет: Когда другим участникам беседы будет полезно увидеть ответ вашей цепочки, вы можете отправить свой ответ обратно на канал или в главное окно DM.Просто установите флажок под вашим сообщением перед его отправкой.
Вы будете получать уведомления о новых ответах на обсуждение, если вы начали обсуждение, ответили на него или были упомянуты в исходном сообщении или ответах на него. Если вы не участвуете в беседе, вы можете подписаться на нее, чтобы оставаться в курсе. Чтобы перестать получать уведомления о новой активности, вы можете отписаться от обсуждения в любой момент.
Настольный
iOS
Android
- Наведите указатель мыши на нить.
- Щелкните значок из трех точек .
- Выберите Следуйте за веткой , чтобы получать уведомления обо всех новых ответах за цепочку, или Отмените цепочку , чтобы перестать получать уведомления.
- Постучите по резьбе.
- Коснитесь значка из трех точек под исходным сообщением.
- Выберите Follow Thread , чтобы получать уведомления обо всех новых ответах на обсуждения, или Unfollow Thread , чтобы прекратить получение уведомлений.
- Постучите по резьбе.
- Коснитесь значка из трех точек под исходным сообщением.
- Выберите Follow Thread , чтобы получать уведомления обо всех новых ответах на обсуждения, или Unfollow Thread , чтобы прекратить получение уведомлений.
Настольный
iOS
Android
Выберите Темы в верхней части левой боковой панели, чтобы увидеть все цепочки, за которыми вы подписаны, где цепочки с непрочитанными ответами будут отображаться вверху списка.В представлении Threads вы можете сделать следующее:
На вкладке Home нажмите Threads в верхней части экрана, чтобы увидеть все беседы, за которыми вы следите, где потоки с непрочитанными ответами появятся вверху списка. В представлении Threads вы можете сделать следующее:- Чтобы добавить в беседу, нажмите Ответить .
- Отмените подписку, если вы больше не хотите получать уведомления о новых ответах.
- Чтобы добавить в беседу, нажмите Ответить .
- Отмените подписку, если вы больше не хотите получать уведомления о новых ответах.
Совет: Прочитав ответ в цепочке, к которому вы хотите вернуться позже, вы можете пометить сообщение как непрочитанное.
Кто может использовать эту функцию?- Все участников и гостей
- Free , Standard , Plus и Enterprise Grid планы
Отлично!
Большое спасибо за ваш отзыв!
Если вы хотите, чтобы сотрудник нашей службы поддержки ответил вам, отправьте сообщение по адресу feedback @ slack.