In order to play the star water cup, I studied it with my teammates in fishing raids, mainly the knowledge of multithreading, multi process and decorators. I know a little about it
Multithreading
My understanding is to open a new thread to execute the functions I assigned to it
_
t
h
r
e
a
d
.
s
t
a
r
t
_
n
e
w
_
t
h
r
e
a
d
(
f
u
n
c
t
i
o
n
n
a
m
e
,
a
r
g
s
)
\_thread.start\_new\_thread(function_{name}, args)\\
_thread.start_new_thread(functionname,args)
Where args is given in tuple form
I learned it first_ thread
import _thread import time def print_time(outthing, delay): count = 2 while count > 0: time.sleep(delay) count -= 1 print("{}: now time is: {}".format(outthing, time.ctime(time.time()) )) try: _thread.start_new_thread(print_time, ("Thread1", 1, ) ) _thread.start_new_thread(print_time, ("Thread2", 3, ) ) except KeyboardInterrupt: print("What do you care about him") while True: pass
Operation results
Thread1: now time is: Fri Nov 19 11:10:37 2021 Thread1: now time is: Fri Nov 19 11:10:38 2021 Thread2: now time is: Fri Nov 19 11:10:39 2021 Thread2: now time is: Fri Nov 19 11:10:42 2021
But the Internet says this thing has been eliminated, so we use it
t
h
r
e
a
d
i
n
g
threading
threading
Use the Threading module to create threads directly from
t
h
r
e
a
d
i
n
g
.
T
h
r
e
a
d
threading.Thread
threading.Thread inherits and then overrides__
i
n
i
t
init
init__ Methods and
r
u
n
run
run method:
import time import threading class MyThread(threading.Thread): def __init__(self, ThreadID, delay, counter): threading.Thread.__init__(self) self.ThreadID = ThreadID self.delay = delay self.counter = counter def run(self): print("thread {}Start running".format(self.ThreadID)) print_time(self.ThreadID, self.delay, self.counter) print("thread {}End operation".format(self.ThreadID)) def print_time(ThreadID, delay, t): count = t while count > 0: if Wrong_exit == 1: print("Error") time.sleep(delay) print("thread {}Is running. The current time is:{}".format(ThreadID, time.ctime(time.time()))) count -= 1 Wrong_exit = 0 f1 = MyThread("thread1", 1, 5) f2 = MyThread("thread2", 2, 3) f3 = MyThread("thread3", 4, 2) f1.start() f2.start() f3.start() f1.join() f2.join() # The three join s here ensure that the main thread will not end until all three sub threads have ended f3.join() # Otherwise, it may occur that all threads are output first, and then thread is output to end the operation print("All threads finished executing")
Operation results
You can see that thread 123 is running at the same time
thread thread1 Start running thread thread2 Start running thread thread3 Start running thread thread1 Is running. The current time is: Fri Nov 19 11:41:02 2021 thread thread2 Is running. The current time is: Fri Nov 19 11:41:03 2021 thread thread1 Is running. The current time is: Fri Nov 19 11:41:03 2021 thread thread1 Is running. The current time is: Fri Nov 19 11:41:04 2021 thread thread3 Is running. The current time is: Fri Nov 19 11:41:05 2021 thread thread2 Is running. The current time is: Fri Nov 19 11:41:05 2021 thread thread1 Is running. The current time is: Fri Nov 19 11:41:05 2021 thread thread1 Is running. The current time is: Fri Nov 19 11:41:06 2021 thread thread1 End operation thread thread2 Is running. The current time is: Fri Nov 19 11:41:07 2021 thread thread2 End operation thread thread3 Is running. The current time is: Fri Nov 19 11:41:09 2021 thread thread3 End operation All threads finished executing
t h r e a d thread thread also provides the following methods
r u n ( ) run() run(): the method used to represent thread activity.
s t a r t ( ) start() start(): start thread activity.
j
o
i
n
(
[
t
i
m
e
]
)
join([time])
join([time]): wait until the thread aborts. This blocks the calling thread until the thread's join() method is called to abort - normal exit or throw
Unhandled exception - or an optional timeout occurred.
for example
.
j
o
i
n
(
5
)
.join(5)
. join(5), wait up to
5
s
5s
5s or to the end of the call
i s A l i v e ( ) isAlive() isAlive(): Returns whether the thread is active.
g e t N a m e ( ) getName() getName(): returns the thread name.
s e t N a m e ( ) setName() setName(): sets the thread name.
j o i n ( ) join() join() can be seen in the above example
t h r e a d i n g threading threading support L o c k Lock Lock to achieve thread synchronization, also support Q u e u e Queue Queue is convenient for multiple threads to access together. Only L o c k Lock Lock to achieve synchronization, Q u e u e Queue The Queue is placed in the process
import threading import time class MyThread(threading.Thread): def __init__(self, t_name, delay, q, counter): # Record thread name, delay time, lock used, and number of broadcasts threading.Thread.__init__(self) self.delay = delay self.name = t_name self.q = q self.counter = counter def run(self): print("{} begin running".format(self.name)) print_time(self.name, self.delay, self.q, self.counter) def print_time(name, delay, q, counter): q.acquire() # Lock while counter > 0: time.sleep(delay) print("{} tells you, now time is: {} ".format(name, time.ctime())) counter -= 1 print("") q.release() # Unlock at the end of the last thread if __name__ == "__main__": queueLock = threading.Lock() q1 = MyThread("q1", 1, queueLock, 3) q2 = MyThread("q2", 2, queueLock, 2) q1.start() q2.start()
The operation results are obvious
q1 and q2 are started at the same time, but q2 starts only after q1 ends
q1 begin running q2 begin running q1 tells you, now time is: Fri Nov 19 11:25:28 2021 q1 tells you, now time is: Fri Nov 19 11:25:29 2021 q1 tells you, now time is: Fri Nov 19 11:25:30 2021 q2 tells you, now time is: Fri Nov 19 11:25:32 2021 q2 tells you, now time is: Fri Nov 19 11:25:34 2021
Multi process
My understanding is to open a new process to execute the functions I assigned to it. How is it similar to a thread
We use
m
u
l
t
i
p
r
o
c
e
s
s
i
n
g
multiprocessing
multiprocessing class
p
=
m
u
l
t
i
p
r
o
c
e
s
s
i
n
g
.
P
r
o
c
e
s
s
(
t
a
r
g
e
t
=
f
u
n
c
,
a
r
g
s
=
element
group
)
p = multiprocessing.Process(target = func, args = tuple)
p=multiprocessing.Process(target=func,args = tuple)
f
u
n
c
func
func is the name of the function,
a
r
g
s
args
args is the parameter group provided in tuple form
import multiprocessing import time def print_time(delay, counter, Proname): while counter > 0: print("{} tells you, now time is: {}".format(Proname, time.ctime())) time.sleep(delay) counter -= 1 if __name__ == '__main__': # This sentence must be added f1 = multiprocessing.Process(target=print_time, args=(2, 2, "Pro1")) f2 = multiprocessing.Process(target=print_time, args=(1, 3, "Pro2")) f1.start() f2.start()
result
Pro2 tell s you,now time is :Fri Nov 19 11:46:20 2021 Pro1 tell s you,now time is :Fri Nov 19 11:46:20 2021 Pro2 tell s you,now time is :Fri Nov 19 11:46:21 2021 Pro1 tell s you,now time is :Fri Nov 19 11:46:22 2021 Pro2 tell s you,now time is :Fri Nov 19 11:46:22 2021
We define a process as a class from
m
u
l
t
i
p
r
o
c
e
s
s
i
n
g
.
P
r
o
c
e
s
s
multiprocessing.Process
multiprocessing.Process to inherit
This piece is similar to threads
import multiprocessing import time class MyProcess(multiprocessing.Process): def __init__(self, Proname, delay, counter): multiprocessing.Process.__init__(self) self.name = Proname self.delay = delay self.counter = counter def run(self): print("{} start running".format(self.name)) print_time(self.name, self.delay, self.counter) print("{} end running".format(self.name)) def print_time(Proname, delay, counter): while counter > 0: counter -= 1 time.sleep(delay) print("{} tells you now time is {}".format(Proname, time.ctime())) if __name__ == "__main__": MyPro1 = MyProcess("p1", 1, 3) MyPr02 = MyProcess("p2", 2, 2) MyPro1.start() MyPr02.start()
result
p1 start running p2 start running p1 tells you now time is Fri Nov 19 11:47:57 2021 p2 tells you now time is Fri Nov 19 11:47:58 2021 p1 tells you now time is Fri Nov 19 11:47:58 2021 p1 tells you now time is Fri Nov 19 11:47:59 2021 p1 end running p2 tells you now time is Fri Nov 19 11:48:00 2021 p2 end running
method:
i
s
_
a
l
i
v
e
(
)
,
j
o
i
n
(
[
t
i
m
e
o
u
t
]
)
,
r
u
n
(
)
,
s
t
a
r
t
(
)
,
t
e
r
m
i
n
a
t
e
(
)
is\_alive(),join([timeout]),run(),start(),terminate()
is_alive(),join([timeout]),run(),start(),terminate(). Among them,
P
r
o
c
e
s
s
Process
Process to
s
t
a
r
t
(
)
start()
start() starts a process.
I used one
d
a
e
m
o
n
daemon
daemon
d
a
e
m
o
n
daemon
The daemon is automatically terminated after the parent process terminates, and it cannot generate a new process itself. It must be in the parent process
s
t
a
r
t
(
)
start()
Set before start(). For example:
p = multiprocessing.Process(target = worker, args = (3,)) p.daemon = True
Some components
Lock()
When multiple processes need to access shared resources,
L
o
c
k
Lock
Lock can be used to avoid access conflicts.
Just lock it and let only one run
There are two ways to write, one is to use
w
i
t
h
with
with, one is standard
.
a
c
q
u
i
r
e
(
)
.acquire()
.acquire()
import multiprocessing class MyProcess(multiprocessing.Process): def __init__(self, Proname, f, times, lock): multiprocessing.Process.__init__(self) self.f = f self.lock = lock self.name = Proname self.times = times '''def run(self): fs = open(self.f, 'a+') fs.write("{} is running\n".format(self.name)) fs.close() with self.lock: # Lock it here while self.times > 0: getF(self.name, self.times, open(self.f, 'a+')) self.times -= 1 # Unlock here fs = open(self.f, 'a+') fs.write("{} is ending\n".format(self.name)) fs.write("\n") fs.close()''' def run(self): fs = open(self.f, 'a+') fs.write("{} is starting\n".format(self.name)) fs.close() self.lock.acquire() # Lock while self.times > 0: self.times -= 1 getF(self.name, self.times, open(self.f, 'a+')) fs = open(self.f, 'a+') fs.write("{} is ending\n".format(self.name)) fs.write("\n") self.lock.release() # Unlock fs.close() def getF(name, times, f): f.write(name + "\n") f.close() if __name__ == "__main__": lock = multiprocessing.Lock() p1 = MyProcess("p1", "readme.txt", 5, lock) p2 = MyProcess("p2", "readme.txt", 3, lock) p1.start() p2.start() print("end")
Output results (from file)
p1 is starting p2 is starting p1 p1 p1 is ending p2 p2 is ending
Semaphore and Event
S
e
m
a
p
h
o
r
e
Semaphore
Semaphore
Used to control the number of accesses to shared resources, such as the maximum number of connections to the pool.
s
=
m
u
l
t
i
p
r
o
c
e
s
s
i
n
g
.
S
e
m
a
p
h
o
r
e
(
2
)
s = multiprocessing.Semaphore(2)
s=multiprocessing.Semaphore(2) can only run two processes at the same time (excluding the main process), which is actually the upper limit of the remaining position 2
s
.
a
c
q
u
i
r
e
(
)
s.acquire()
s. The acquire () process occupies one location, and the number of remaining locations is reduced by one to 1
s
.
r
e
l
e
a
s
e
(
)
s.release()
s. The release () process gives up its position, and the remaining positions are added by one back to 2
When the remaining position becomes 0, then
a
c
q
u
i
r
e
acquire
acquire has to wait for a process to give way
E
v
e
n
t
Event
Event
He can let a group wait until one or more processes are executed before running
e
e
=
m
u
l
t
i
p
r
o
c
e
s
s
i
n
g
.
E
v
e
n
t
(
)
ee = multiprocessing.Event()
ee=multiprocessing.Event()
e . w a i t ( ∣ t i m e ∣ ) e.wait(|time|) e.wait(∣ time ∣) at time t i m e time Before or e . i s _ s e t ( ) e.is\_set() e.is_set() becomes T r u e True Wait until True
e . s e t ( ) e.set() e.set() enable e . i s _ s e t ( ) e.is\_set() e.is_set() becomes T r u e True True
e . c l e a r ( ) e.clear() e. Clear e . i s _ s e t ( ) e.is\_set() e.is_set() becomes F a l s e False False
I used the above two to write a very interesting car crossing the road(
E
v
e
n
t
Event
Event control)
There are two lights. The car can pass only when they turn green. The red light of the two lights can only wait one at a time
(
S
e
m
a
p
h
o
r
e
Semaphore
Semaphore control)
import multiprocessing import time class MyProcess(multiprocessing.Process): def __init__(self, process_name, e): multiprocessing.Process.__init__(self) self.process_name = process_name self.e = e def run(self): print("car {} come".format(self.process_name)) car(self.e, self.process_name) class Light(multiprocessing.Process): def __init__(self, last, s, name): multiprocessing.Process.__init__(self) self.last = last self.s = s self.name = name def run(self): light(self.s, self.name, self.last) def light(s, name, last): s.acquire() time.sleep(last) print("light " + name + " is green\n") s.release() def car(e, car_name): if not e.is_set(): print("red, {} can't go\n".format(car_name)) e.wait() # Wait for the green light print("green, {} go go go".format(car_name)) if __name__ == "__main__": ss = multiprocessing.Semaphore(1) # The lights can only change one at a time ee = multiprocessing.Event() cars = [] for i in range(1, 6): # Six cars f = MyProcess("p" + str(i), ee) cars.append(f) f.start() l1 = Light(2, ss, "l1") l2 = Light(3, ss, "l2") l2.start() l1.start() while True: num = 0 if l1.is_alive(): num += 1 if l2.is_alive(): num += 1 # Judge whether it's all over if num == 0: ee.set() print("all lights are green\n") break try: while True: # Monitor every second to see if all the cars have passed flag = 1 for i in cars: if i.is_alive(): flag = 0 if flag == 0: time.sleep(1) exit(0) except KeyboardInterrupt: print("Manual block") except UnboundLocalError: print("Variable unnamed") finally: print("all car across")
result
car p1 come red, p1 can't go car p2 come red, p2 can't go car p3 come red, p3 can't go car p4 come red, p4 can't go car p5 come red, p5 can't go light l1 is green light l2 is green all lights are green green, p1 go go go green, p2 go go go green, p3 go go go green, p5 go go go green, p4 go go go all car across
Queue
Provide a queue that can be accessed by all processes
p
u
t
put
put method
To insert data into the queue, the put method also has two optional parameters:
b
l
o
c
k
e
d
blocked
blocked and
t
i
m
e
o
u
t
timeout
timeout.
If
b
l
o
c
k
e
d
blocked
blocked is
T
r
u
e
True
True (default), and
t
i
m
e
o
u
t
timeout
If timeout is positive, the method blocks
t
i
m
e
o
u
t
timeout
timeout the specified time until the queue has free space. If it times out, it will be thrown
Q
u
e
u
e
.
F
u
l
l
Queue.Full
Queue.Full exception.
If
b
l
o
c
k
e
d
blocked
blocked is
F
a
l
s
e
False
False, but the
Q
u
e
u
e
Queue
If the Queue is full, it will be thrown immediately
Q
u
e
u
e
.
F
u
l
l
Queue.Full
Queue.Full exception.
g
e
t
get
get method
Reads and deletes an element from the queue. Again,
g
e
t
get
The get method has two optional parameters:
b
l
o
c
k
e
d
blocked
blocked and
t
i
m
e
o
u
t
timeout
timeout.
If
b
l
o
c
k
e
d
blocked
blocked is
T
r
u
e
True
True (default), and
t
i
m
e
o
u
t
timeout
If timeout is a positive value, if no element is retrieved during the waiting time, an error will be thrown
Q
u
e
u
e
.
E
m
p
t
y
Queue.Empty
Queue.Empty exception.
If
b
l
o
c
k
e
d
blocked
blocked is
F
a
l
s
e
False
False, there are two situations, if
Q
u
e
u
e
Queue
If the Queue has a value available, the value is returned immediately. Otherwise, if the Queue is empty, it is thrown immediately
Q
u
e
u
e
.
E
m
p
t
y
Queue.Empty
Queue.Empty exception.
Event is used to ensure that all data are inserted and then retrieved
import multiprocessing import time class WriteProcess(multiprocessing.Process): def __init__(self, number, q): multiprocessing.Process.__init__(self) self.number = number self.q = q def run(self): print("wait for write") write_text(self.number, self.q) class ReadProcess(multiprocessing.Process): def __init__(self, q, loc): multiprocessing.Process.__init__(self) self.q = q self.loc = loc def run(self): read_text(self.q, self.loc) def write_text(get_in, q): try: q.put(get_in, block=False) except: pass finally: print("successfully get in") def read_text(q, loc): try: loc.wait() print("wait for read") while q.qsize() > 0: print("successfully get out: ", q.get(block=False)) except : print("blank queue") if __name__ == "__main__": lo = multiprocessing.Event() a = int(input()) b = int(input()) qq = multiprocessing.Queue() q1 = WriteProcess(a, qq) q2 = WriteProcess(b, qq) q3 = ReadProcess(qq, lo) q1.start() q2.start() q3.start() while True: num = 0 if q1.is_alive(): num += 1 if q2.is_alive(): num += 1 if num == 0: lo.set() break
result
4 5 wait for write wait for write successfully get in successfully get in wait for read successfully get out: 5 successfully get out: 4
Pipe
If you don't use it, it seems to coo
Pool
Feeling and
S
e
m
a
p
h
o
r
e
Semaphore
Semaphore is a bit like, you can choose asynchronous and parallel steps
a
p
p
l
y
,
a
s
y
n
c
apply,_async
apply,async
(
f
u
n
c
,
a
r
g
s
)
(func, args)
(func,args) it is non blocking
His return value needs to be written
c
a
l
l
b
a
c
k
callback
callback parameter
p
o
o
l
1
=
m
u
l
t
i
p
r
o
c
e
s
s
i
n
g
.
P
o
o
l
(
p
r
o
c
e
s
s
e
s
=
2
)
pool1 = multiprocessing.Pool(processes=2)
pool1=multiprocessing.Pool(processes=2)
p
o
o
l
1.
a
p
p
l
y
_
a
s
y
n
c
(
p
r
i
n
t
_
t
i
m
e
,
(
element
group
)
,
c
a
l
l
b
a
c
k
=
o
u
t
)
pool1.apply\_async(print\_time, (tuple), callback=out)
pool1.apply_async(print_time, (tuple), callback=out)
p
r
i
n
t
_
t
i
m
e
print\_time
print_time and
o
u
t
out
out is a function,
o
u
t
out
The function parameter of out is
p
r
i
n
t
_
t
i
m
e
print\_time
print_ Return value of time
a p p l y apply apply ( f u n c , a r g s ) (func, args) (func,args) is blocked, and the return value is directly the return value after the process runs
c l o s e ( ) close() close() close p o o l pool pool so that it is no longer accepting new tasks.
t e r m i n a t e ( ) terminate() terminate() ends the work process and does not process unfinished tasks.
j
o
i
n
(
)
join()
join() the main process is blocked and waits for the child process to exit,
j
o
i
n
join
The join method should be
c
l
o
s
e
close
close or
t
e
r
m
i
n
a
t
e
terminate
Use after terminate.
import multiprocessing import time def print_time(name, delay, counter): while counter > 0: print("{} tells you, now time is {}".format(name, time.ctime())) time.sleep(delay) counter -= 1 return "done" + name def out(msg): print("now" + msg) if __name__ == "__main__": result = [] pool1 = multiprocessing.Pool(processes=2) for i in range(1, 5): pool1.apply_async(print_time, ("p" + str(i), i, 5 - i,), callback=out) pool1.close() pool1.join() pool = multiprocessing.Pool(processes=2) for i in range(1, 5): result.append(pool.apply(print_time, ("p" + str(i), i, 5 - i,))) pool.close() pool.join() for res in result: print("now" + res)
Decorator
Divided into with and without parameters
Class decorators and function decorators
Function decorator without parameters
import time def showtime(func): def wrapper(): start_time = time.time() func() end_time = time.time() print('spend is {}'.format(end_time - start_time)) return wrapper @showtime def foo(): print('foo..') foo()
Decorator with parameters (decorating function)
def outside(flag=0): def show_times(func): def count(a, b): start_time = time.time() func(a, b) end_time = time.time() print("spend is {}".format(end_time - start_time)) if flag == 1: print("I'm special") return count return show_times @outside(0) def test(a, b): print(a+b) time.sleep(2) a1 = int(input()) b1 = int(input()) test(a1, b1)
Class decorator
Mainly through internal__
c
a
l
l
call
call__ method
import time class Decor: def __init__(self, func): self.func = func def __call__(self, a, b): start_time = time.time() self.func(a, b) end_time = time.time() print("It costs {}".format(end_time - start_time)) @Decor def test(a, b): print(a + b) time.sleep(2) a1 = int(input()) b1 = int(input()) test(a1, b1)