Thread.sleep метод
Содержание:
Использование time.sleep() в threading
Python является хорошим примером использования . Модуль логирования logging является потоко-безопасным, поэтому в данном примере он будет полезнее, чем операторы . В основе следующего кода лежит данный пример:
Python
import logging
import threading
import time
def worker(arg):
while not arg:
logging.debug(«рабочий поток вносится»)
time.sleep(1)
def main():
logging.basicConfig(
level=logging.DEBUG,
format=»%(relativeCreated)6d %(threadName)s %(message)s»
)
info = {«stop»: False}
thread = threading.Thread(target=worker, args=(info,))
thread_two = threading.Thread(target=worker, args=(info,))
thread.start()
thread_two.start()
while True:
try:
logging.debug(«Добавление из главного потока»)
time.sleep(0.75)
except KeyboardInterrupt:
info = True
logging.debug(‘Остановка’)
break
thread.join()
thread_two.join()
if __name__ == «__main__»:
main()
1 9 25 |
importlogging importthreading importtime defworker(arg) whilenotarg»stop» logging.debug(«рабочий поток вносится») defmain() logging.basicConfig( level=logging.DEBUG, format=»%(relativeCreated)6d %(threadName)s %(message)s» ) info={«stop»False} thread=threading.Thread(target=worker,args=(info,)) thread_two=threading.Thread(target=worker,args=(info,)) thread.start() thread_two.start() whileTrue try logging.debug(«Добавление из главного потока») exceptKeyboardInterrupt info»stop»=True logging.debug(‘Остановка’) break thread.join() thread_two.join() if__name__==»__main__» main() |
Здесь для создания двух потоков используется модуль Python . Также создается объект входа, что будет вводить в . Затем начинаются оба потока и инициируется цикл для каждого входа из главного потока. Для фиксирования пользователя используется при нажатии .
Попробуйте запустить вышеуказанный код в терминале. Ваш вывод должен походить на следующий:
Shell
2 Thread-1 рабочий поток вносится
4 Thread-2 рабочий поток вносится
4 MainThread Добавление из главного потока
755 MainThread Добавление из главного потока
1004 Thread-1 рабочий поток вносится
1006 Thread-2 рабочий поток вносится
1506 MainThread Добавление из главного потока
2005 Thread-1 рабочий поток вносится
2007 Thread-2 рабочий поток вносится
2257 MainThread Добавление из главного потока
3007 Thread-1 рабочий поток вносится
3008 MainThread Добавление из главного потока
1 |
2Thread-1рабочийпотоквносится 4Thread-2рабочийпотоквносится 4MainThreadДобавлениеизглавногопотока 755MainThreadДобавлениеизглавногопотока 1004Thread-1рабочийпотоквносится 1006Thread-2рабочийпотоквносится 1506MainThreadДобавлениеизглавногопотока 2005Thread-1рабочийпотоквносится 2007Thread-2рабочийпотоквносится 2257MainThreadДобавлениеизглавногопотока 3007Thread-1рабочийпотоквносится 3008MainThreadДобавлениеизглавногопотока |
Когда каждый поток работает, а затем уходит в сон, выходные данные выводятся в консоль. Теперь, разобрав пример, вы сможете использовать данные концепции в своем собственном коде.
Sleep for a Duration
C++11 provides a function std::this_thread::sleep_for to block the current thread for specified duration i.e.
template <class Rep, class Period> void sleep_for (const chrono::duration<Rep,Period>& rel_time);
This function accepts a duration as an argument and make the calling thread to sleep for that particular duration.
This duration can be from nanoseconds to hours i.e.
std::chrono::nanoseconds std::chrono::microseconds std::chrono::milliseconds std::chrono::seconds std::chrono::minutes std::chrono::hours
Lets see some examples,
Sleeping a Thread for MilliSeconds:
To sleep a thread for 200 Milliseconds call sleep_for with following argument i.e.
std::this_thread::sleep_for(std::chrono::milliseconds(200));
Sleeping a Thread for Minutes:
To sleep a thread for 1 Minute call sleep_for with following argument i.e.
std::this_thread::sleep_for(std::chrono::minutes(1));
#include <iostream> #include <thread> #include <chrono> void threadFunc() { int i = 0; while (i < 10) { // Print Thread ID and Counter i std::cout<<std::this_thread::get_id()<<" :: "<<i++<<std::endl; // Sleep this thread for 200 MilliSeconds std::this_thread::sleep_for(std::chrono::milliseconds(200)); } } int main() { std::thread th(&threadFunc); th.join(); return 0; }
Output:
140484807997184 :: 0 140484807997184 :: 1 140484807997184 :: 2 140484807997184 :: 3 140484807997184 :: 4 140484807997184 :: 5 140484807997184 :: 6 140484807997184 :: 7 140484807997184 :: 8 140484807997184 :: 9
Convention
The methods for the handling of time in multithreading programs follow a simple convention. Methods ending with _for have to be parametrized by a time duration; methods ending with _until by a time point. I presented time duration and time point in separate posts. Here is a concise overview of the methods dealing with sleeping, blocking, and waiting.
in2min stand for a time 2 minutes in the future. 2s is a time duration of 2 seconds. Although I use auto it’s very verbose to define the time point in2min: auto in2min= std::chrono::steady_clock::now() + std::chrono::minutes(2). To the rescue we have time literals in C++14 2s is valid C++14. C++14 has more literals for typical time durations.
Now the practice.
An Example of Using the Sleep Command
The following script shows how to use the sleep command to make a terminal-based countdown clock:
#!/bin/bashx=10while dosleep 1sclearecho "$x seconds until blast off"x=$(( $x
Here’s how this script works:
- The script sets the variable x to 10.
- The while loop continues to iterate while the value of x is greater than zero.
- The sleep command pauses the script for 1 second each time around the loop.
- The rest of the script clears the screen each iteration, displays the message, «x seconds until blast off,» and subtracts 1 from the value of x.
Without the sleep command, the script would zoom through, and the messages would display too quickly.
userfaultfd: обработка ошибок памяти в userspace
Думаю, не будет чего-то сильно нового в том, чтобы сказать, что в UNIX-like системах файловые дескрипторы на что только не указывают. Например, на Linux это может быть сокет, pipe, eventfd или даже ссылка на ebpf-программу. Но, возможно, этот пример вас всё-таки удивит. В начале статьи я говорил о том, что для ядра page faults — обычное дело: своп, copy-on-write, вот это всё… Когда же пользовательский процесс «промахивается», ему отправляется SIGSEGV
Насколько я знаю, возврат управления из обработчика SIGSEGV, сгенерированного ядром, является undefined behavior, и тем не менее, существует библиотека GNU libsigsegv, обобщающая особенности обработки ошибки доступа к памяти на различных платформах, даже Windows (ВНИМАНИЕ: лицензия GPL, если не готовы под ней же распространять свою программу, то не используйте libsigsegv). Не так давно в Linux появился абсолютно задокументированный способ, называется : с помощью одноимённого системного вызова вы открываете файловый дескриптор, чтение и запись в который специальных структур являются командами
Имея такой файловый дескриптор, вы можете пометить некий диапазон виртуальных адресов вашего процесса. После этого при первом обращение к каждой помеченной странице памяти, обратившийся поток заснёт, а чтение из файлового дескриптора вернёт информацию о произошедшем. После чего обработчик заполнит ответную структуру с указателем на данные, которые нужно использовать для инициализации «проблемной» страницы, ядро её проинициализирует и разбудит обратившийся поток. При этом предполагается наличие отдельного потока, в чьи обязанности входит чтение команд из дескриптора и выдача ответов. Вообще говоря, через можно получать и другую информацию, например, некоторые уведомления об изменении карты виртуальной памяти процесса.
Notes
If the interval specified in req is not an exact multiple of the granularity underlying clock (see time(7)), then the interval will be rounded
up to the next multiple. Furthermore, after the sleep completes, there may still be a delay before the CPU becomes free to once again execute the calling
thread.
The fact that nanosleep() sleeps for a relative interval can be problematic if the call is repeatedly restarted after being interrupted by signals,
since the time between the interruptions and restarts of the call will lead to drift in the time when the sleep finally completes. This problem can be avoided
by using clock_nanosleep(2) with an absolute time value.
POSIX.1 specifies that nanosleep() should measure time against the CLOCK_REALTIME clock. However, Linux measures the time using the
CLOCK_MONOTONIC clock. This probably does not matter, since the POSIX.1 specification for clock_settime(2) says that discontinuous changes in
CLOCK_REALTIME should not affect nanosleep():
- Setting the value of the CLOCK_REALTIME clock via (2) shall have no effect on threads that are blocked waiting for a relative
time service based upon this clock, including the nanosleep() function; … Consequently, these time services shall expire when the requested relative
interval elapses, independently of the new or old value of the clock.
Old behavior
- In order to support applications requiring much more precise pauses (e.g., in order to control some time-critical hardware), nanosleep() would handle
pauses of up to 2 ms by busy waiting with microsecond precision when called from a thread scheduled under a real-time policy like SCHED_FIFO or
SCHED_RR. This special extension was removed in kernel 2.5.39, hence is still present in current 2.4 kernels, but not in 2.6 kernels.
«Ключевой вопрос математики: не всё ли равно»
Что, если вам нужно узнать, ссылается ли этот файловый дескриптор на ? Казалось бы, — и все дела. Ну, окей…
Упс… Дескриптор-то вроде как один, но алиасы разные. Нам поможет CRIU — Checkpoint/Restore In Userspace. Без паники, я не предлагаю сдампить процесс, посмотреть на результат и загрузить обратно. Просто для нужд своих userspace-инструментов, разработчики из этого проекта, как я понял, добавили в ядро системный вызов : ему передаются два PID, тип ресурса и, собственно, два ресурса, а он говорит, указывают ли они на одну и ту же сущность ядра:
Опять двадцать пять! Подождите ка, а что если…
Ага, тот неловкий момент, когда пытаешься понять, где ошибка, а она оказалась в твоём понимании происходящего. Логично считать, что bash точно так же поступает и с моей программой, как и с !
Не буду утверждать, что это работает всегда и идеально — для этого нужно самому его использовать много и по-разному, но как best effort инструмент для каких-нибудь эвристик наверняка может пригодиться.
Примеры команды Sleep в Bash
Хотя вы можете использовать его непосредственно в оболочке, команда sleep обычно используется для введения задержки в выполнение сценария bash. Мы собираемся показать использование команды sleep через примеры сценариев bash.
Команда sleep без суффикса считается в секундах
Предположим, вы хотите приостановить ваш bash-скрипт на 5 секунд, вы можете использовать режим sleep следующим образом:
sleep 5
В примере скрипта bash это может выглядеть так:
!/bin/bash echo "Sleeping for 5 seconds…" sleep 5 echo "Completed"
Если вы запустите его с помощью команды time, вы увидите, что скрипт bash на самом деле работал (немного) более 5 секунд.
time ./sleep.sh Sleeping for 5 seconds… Completed real 0m5.008s user 0m0.000s sys 0m0.007s
Команда Sleep с суффиксом m, h или d
Вы можете указать время sleep в минутах следующим образом:
sleep 1m
Это приостановит скрипт/оболочку на одну минуту. Если вы хотите отложить сценарий на несколько часов, вы можете сделать это с помощью опции h:
sleep 2h
Даже если вы хотите приостановить скрипт на несколько дней, вы можете сделать это с помощью суффикса d:
sleep 5d
Это может помочь, если вы хотите работать в разные дни или дни недели.
Команда sleep с комбинацией секунд, минут, часов и дня
Вы не обязаны использовать только один суффикс за раз. Вы можете использовать более одного суффикса, и продолжительность sleep является суммой всех суффиксов.
Например, если вы используете следующую команду:
sleep 1h 10m 5s
Это заставит скрипт ждать 1 час 10 минут и 5 секунд. Обратите внимание, что суффикс s здесь по-прежнему необязателен
Бонусный совет: спать меньше секунды
Вы могли заметить, что наименьшая единица времени в команде sleep – секунда. Но что если ваш bash-скрипт будет спать в течение миллисекунд?
Хорошо, что вы можете использовать с плавающей точкой (десятичные точки) с командой sleep.
Поэтому, если вы хотите ввести паузу в 5 миллисекунд, используйте ее следующим образом:
sleep 0.005
Вы также можете использовать десятичные точки с другими суффиксами.
sleep 1.5h 7.5m
Будет введена задержка в 1 час 37 минут и 30 секунд.
Мы надеемся, что вы не спали, читая эти примеры команды sleep -).
Если у вас есть вопросы или предложения, пожалуйста, не стесняйтесь спрашивать.
DESCRIPTION top
nanosleep() suspends the execution of the calling thread until either at least the time specified in *req has elapsed, or the delivery of a signal that triggers the invocation of a handler in the calling thread or that terminates the process. If the call is interrupted by a signal handler, nanosleep() returns -1, sets errno to EINTR, and writes the remaining time into the structure pointed to by rem unless rem is NULL. The value of *rem can then be used to call nanosleep() again and complete the specified pause (but see NOTES). The structure timespec is used to specify intervals of time with nanosecond precision. It is defined as follows: struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; The value of the nanoseconds field must be in the range 0 to 999999999. Compared to sleep(3) and usleep(3), nanosleep() has the following advantages: it provides a higher resolution for specifying the sleep interval; POSIX.1 explicitly specifies that it does not interact with signals; and it makes the task of resuming a sleep that has been interrupted by a signal handler easier.