Million annual salary python road - concurrent programming as much as a thread

Multithreading

1. Process: producer-consumer model

A programming ideas, models, design patterns, theory, etc., are handed you a programming method, and later encountered a similar situation, you can apply

The three elements of the model of producers and consumers:
  1. Manufacturer: generating data
  2. Consumers: receiving data for further processing
  3. Container: buffer (queue) acts as a cushion to balance productivity with consumers, decoupling

2. Thread the theoretical knowledge

  1. What is the thread

    An assembly line workflow

    Process: a process of open space in memory, and then copy all the resources of the primary process, and then call the cpu to execute the code.

    Process is the basic unit of resource scheduling, and the thread is the smallest unit of execution of cpu

    img

    Open process: the process will open up a space in the memory process, the entire process of copying data to a main thread will execute the code inside

  2. Thread vs Process

    1. Open process overhead is very large, much larger than the overhead of thread.
    2. Open thread speed is very fast, faster than the process several times to a hundred times.
    3. A process the same data can be shared between threads and threads, queues, etc. required by the process and method of communication between processes.
  3. Threaded application

    Concurrency: cpu looks like a simultaneous execution of multiple tasks

    A single process to open three threads, concurrent tasks.

    Open three processes concurrent tasks.

    The advantages of open multi-threading: data sharing, small overhead, fast.

The main thread and the child thread no distinction between them

So who is in a process work?

A main thread in the work, when the main thread is finished executing code, have to wait for other threads executing the order to withdraw from the process.

3. Open thread in two ways

** thread does not need to if _ _ name _ _ == '_ _ main _ _': next statement **

The first:

from threading import Thread
import time

def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f"{name} is gone")


if __name__ == '__main__':
    t1 = Thread(target=task,args=("zcy",))
    t1.start()
    print("==main Threading==") # 线程没有主次之分

The second:

from threading import Thread
import time

class MyThread(Thread):

    def __init__(self,name,lst,s):
        super(MyThread, self).__init__()
        self.name = name
        self.lst =lst
        self.s = s

    def run(self):
        print(f"{self.name} is running")
        time.sleep(1)
        print(f"{self.name} is gone")

if __name__ == '__main__':
    t1 = MyThread("zdr",[1,2,3],"180")
    t1.start()
    print("==main thread==")

4. Comparison of code thread vs process

  1. Open speed comparison

    # 多进程
    from multiprocessing import Process
    
    def work():
        print('hello')
    
    def task():
        print('bye')
    
    if __name__ == '__main__':
        # 在主进程下开启线程
        t1 = Process(target=work)
        t2 = Process(target=task)
        t1.start()
        t2.start()
        print('main thread/process')
    # 多线程
    from threading import Thread
    import time
    
    def task(name):
        print(f"{name} is running")
        time.sleep(1)
        print(f"{name} is gone")
    
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task,args=("zdr",))
        t2 = Thread(target=task,args=("zcy",))
        t3 = Thread(target=task,args=("zfy",))
        t4 = Thread(target=task,args=("lfz",))
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        print('==main thread==') # 线程是没有主次之分
  2. Contrast pid

    # 进程
    from multiprocessing import Process
    import time
    import os
    
    def task():
        print(f"子进程:{os.getpid()}")
        print(f"主进程:{os.getppid()}")
    
    
    if __name__ == '__main__':
        p1 = Process(target=task)
        p2 = Process(target=task)
        p1.start()
        p2.start()
    
        print(f"==main{os.getpid()}")
    # 主线程
    from threading import Thread
    import os
    
    def task():
        print(os.getpid())
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t1.start()
        t2.start()
        print(f"===main thread:{os.getpid()}")
  3. Threads share internal data within the same process

    from threading import Thread
    import os
    
    
    x = 3
    def task():
        global x
        x = 100
    
    
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t1.start()
        print(f"===main thread:{x}")
    
    
    # 同一个进程内的资源数据对于这个进程的多个线程来说是共享的.

Small Exercise:

import multiprocessing
import threading

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',8080))
s.listen(5)

def action(conn):
    while True:
        data=conn.recv(1024)
        print(data)
        conn.send(data.upper())

if __name__ == '__main__':

    while True:
        conn,addr=s.accept()


        p=threading.Thread(target=action,args=(conn,))
        p.start()

多线程并发的socket服务端
import socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if not msg:continue

    s.send(msg.encode('utf-8'))
    data=s.recv(1024)
    print(data)

客户端

5. Other relevant thread

Thread object:

Thread .isAlive () # determine whether the thread is alive

Thread .getname () # Get the Thread name

Thread .setname () # set the thread name ***

Method of threading module:

threading.currentThread () # get the object of the current process

threading.enumerate () # returns a list of all the thread objects

threading.activeCount () # returns a number that indicates the number of threads still alive

from threading import Thread, currentThread, enumerate,activeCount
import os
import time

x = 3
def task():
    # print(currentThread())
    # time.sleep(1)
    print("123")


if __name__ == '__main__':
    t1 = Thread(target=task,name="xc-1")
    t2 = Thread(target=task,name="xc-2")
    # name 设置线程名
    t1.start()
    t2.start()
    # time.sleep(2)
    # print(t1.isAlive()) # 判断线程是否存活
    # print(t1.getName()) # 获取线程名
    # t1.setName("zcy-01")
    # print(t1.name)      # ***



    # threading方法
    # print(currentThread())     # 获取当前线程的对象
    # print(currentThread().name)     # 获取当前线程的对象
    print(enumerate())      # 返回一个列表,包含所有的线程对象
    print(activeCount())
    print(f"===main thread:{os.getpid()}")

6.join and daemon threads

Then execute after blocking the main thread to inform the main thread to wait for the child thread is finished: join

# 线程join
from threading import Thread
import time

def task(name):
    print(f"{name} is running")
    time.sleep(1)
    print(f'{name} is gone')


if __name__ == '__main__':
    start_time = time.time()
    t1 = Thread(target=task,args=("zdr",))
    t2 = Thread(target=task,args=("zcy",))
    t3 = Thread(target=task,args=("zfy",))

    t1.start()
    t1.join()
    t2.start()
    t2.join()
    t3.start()
    t3.join()

    print(f"===main thread:{time.time() - start_time}")

Daemon thread:

Whether it is a process or thread, follow: Guardian xxx xxx will wait for the main run is finished after destruction

It is emphasized that: not finished running terminates

#1.对主进程来说,运行完毕指的是主进程代码运行完毕

#2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕

Detailed explanation:

#1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,

#2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

To compare daemons:

from multiprocessing import Process
import time

def foo():
    print(123)
    time.sleep(1)
    print("end123")



def bar():
    print(456)
    time.sleep(2)
    print("end456")


if __name__ == '__main__':
    p1 = Process(target=foo)
    p2 = Process(target=bar)

    p1.daemon = True
    p1.start()
    p2.start()
    print('====main====')

Daemon thread:

from threading import Thread
import time


def sayhi(name):
    print('bye~')
    time.sleep(2)
    print(f'{name} say hello ')


if __name__ == '__main__':
    t = Thread(target=sayhi,args=('zcy',))
    # t.setDaemon(True)
    t.daemon = True
    t.start()

    print('主线程')
from threading import Thread
import time


def foo():
    print(123)  # 1
    time.sleep(1)
    print('end123') # 4


def bar():
    print(456)  # 2
    time.sleep(3)
    print('en456')  # 3


t1 = Thread(target=foo)
t2 = Thread(target=bar)


t1.daemon = True
t1.start()
t2.start()
print('=====main====')  # 3



结果:
123
456
=====main====
end123
en456   

# 主线程什么时候结束?
# 主线程等待非守护子线程结束之后,结束
from threading import Thread
import time

def foo():
    print(123)  # 1
    time.sleep(3)
    print("end123")  

def bar():
    print(456)   # 2
    time.sleep(1)
    print("end456")  # 4


t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")  # 3


结果:
123
456
main-------
end456

7. mutex

from threading import Thread
import time
import random

x = 100

def task():
    time.sleep(random.randint(1,2))
    global x
    temp = x
    time.sleep(random.randint(1,3))
    temp = temp - 1
    x = temp


if __name__ == '__main__':
    l = []
    for i in range(100):
        t = Thread(target=task)
        l.append(t)
        t.start()

    for i in l:
        i.join()

    print(f"main:{x}")
    
    
    
    
# 多个任务共抢一个数据,要保证数据的安全性,要让他们串行
# 给线程加锁
from threading import Thread
from threading import Lock
import time
import random
x = 100

def task(lock):

    lock.acquire()
    # time.sleep(random.randint(1,2))
    global x
    temp = x
    time.sleep(0.01)
    temp = temp - 1
    x = temp
    lock.release()


if __name__ == '__main__':
    mutex = Lock()
    l1 = []
    for i in range(100):
        t = Thread(target=task,args=(mutex,))
        l1.append(t)
        t.start()

    time.sleep(3)
    print(f'主线程{x}')

Guess you like

Origin www.cnblogs.com/zhangchaoyin/p/11415382.html