欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python多线程多进程

程序员文章站 2024-03-17 17:40:28
...

参考博客

https://www.cnblogs.com/whatisfantasy/p/6440585.html

1 概念梳理:
1.1 线程
1.1.1 什么是线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。一个线程是一个execution context(执行上下文),即一个cpu执行时所需要的一串指令。
1.1.2 线程的工作方式
假设你正在读一本书,没有读完,你想休息一下,但是你想在回来时恢复到当时读的具体进度。有一个方法就是记下页数、行数与字数这三个数值,这些数值就是execution context。如果你的室友在你休息的时候,使用相同的方法读这本书。你和她只需要这三个数字记下来就可以在交替的时间共同阅读这本书了。
线程的工作方式与此类似。CPU会给你一个在同一时间能够做多个运算的幻觉,实际上它在每个运算上只花了极少的时间,本质上CPU同一时刻只干了一件事。它能这样做就是因为它有每个运算的execution context。就像你能够和你朋友共享同一本书一样,多任务也能共享同一块CPU。
1.2 进程
一个程序的执行实例就是一个进程。每一个进程提供执行程序所需的所有资源。(进程本质上是资源的集合)
一个进程有一个虚拟的地址空间、可执行的代码、操作系统的接口、安全的上下文(记录启动该进程的用户和权限等等)、唯一的进程ID、环境变量、优先级类、最小和最大的工作空间(内存空间),还要有至少一个线程。
每一个进程启动时都会最先产生一个线程,即主线程。然后主线程会再创建其他的子线程。
1.3 进程与线程区别
1.同一个进程中的线程共享同一内存空间,但是进程之间是独立的。

2.同一个进程中的所有线程的数据是共享的(进程通讯),进程之间的数据是独立的。

3.对主线程的修改可能会影响其他线程的行为,但是父进程的修改(除了删除以外)不会影响其他子进程。

4.线程是一个上下文的执行指令,而进程则是与运算相关的一簇资源。

5.同一个进程的线程之间可以直接通信,但是进程之间的交流需要借助中间代理来实现。

6.创建新的线程很容易,但是创建新的进程需要对父进程做一次复制。

7.一个线程可以操作同一进程的其他线程,但是进程只能操作其子进程。

8.线程启动速度快,进程启动速度慢(但是两者运行速度没有可比性)。

2 多线程
2.1 线程常用方法
python多线程多进程
2.1.1 Thread类
1.普通创建方式

import threading
import time

def run(n):
    print("task", n)
    time.sleep(1)
    print('2s')
    time.sleep(1)
    print('1s')
    time.sleep(1)
    print('0s')
    time.sleep(1)

t1 = threading.Thread(target=run, args=("t1",))
t2 = threading.Thread(target=run, args=("t2",))
t1.start()
t2.start()

"""
task t1
task t2
2s
2s
1s
1s
0s
0s
"""

2.继承threading.Thread来自定义线程类
其本质是重构Thread类中的run方法

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, n):
        super(MyThread, self).__init__()  # 重构run函数必须要写
        self.n = n

    def run(self):
        print("task", self.n)
        time.sleep(1)
        print('2s')
        time.sleep(1)
        print('1s')
        time.sleep(1)
        print('0s')
        time.sleep(1)


if __name__ == "__main__":
    t1 = MyThread("t1")
    t2 = MyThread("t2")

    t1.start()
    t2.start()

多线程实例

# -- coding: utf-8 --
import cv2
import numpy as np
#引入多线程模块
import threading
i=1
t_lock=threading.Lock()
class read_frame(threading.Thread):
    def __init__(self,cap):
        threading.Thread.__init__(self)
        self.cap = cap
    def run(self):
        global ret,frame
        while ret:
            t_lock.acquire()
            ret,frame=self.cap.read()
            global i
            print("1_thred number is {}".format(i + 2))
            cv2.imshow("display",frame)
            t_lock.release()
            if cv2.waitKey(1)==ord("q"):
                break;

class detect_frame(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global frame
        while ret:
            global i
            t_lock.acquire()
            cv2.putText(frame,"hello",(40,40),cv2.FONT_HERSHEY_SIMPLEX,4,(127,127,255),2)
            cv2.imshow("2_threading",frame)
            print("2_thred number is {}".format(i-1))
            t_lock.release()
            if cv2.waitKey(1) == ord("q"):
                break

cap = cv2.VideoCapture(0)
ret, frame = cap.read()
read_frame_threaing=read_frame(cap)
read_frame_threaing.start()
putText_threading=detect_frame()
putText_threading.start()

read_frame_threaing.join()
putText_threading.join()

多进程

# -- coding: utf-8 --
import cv2
from threading import Thread
from multiprocessing import Process,Manager
import time
from queue import LifoQueue
import configparser
#采用两个进程同时获得微波与摄像头的数据,摄像头采用两个线程,一个线程读取,另一个线程保存数据。
def get_video(file_name,dic):
    q = LifoQueue()
    def get_frames(q):
        cap = cv2.VideoCapture("video3.MKV")
        while cap.isOpened():
            t1 = time.time()
            ret, frame = cap.read()
            t2 = time.time()
            if ret:
                q.put((frame, (t1 + t2) / 2.))
            #if dic['end']==False:
            #    break
        else:
            print('Camera cannot open.')
            q.put(([], ''))
        cap.release()

    def save_frames(q):
        file_name = './1.mp4'
        f = open(file_name + '_video.log', 'w')
        video_frame_id = 1
        total = float(1) * 60 * 15
        fourcc = cv2.VideoWriter_fourcc(*"MJPG")
        writer = cv2.VideoWriter(file_name + '.avi', fourcc, 15, (640,480))
        while True:
            ts = time.time()
            frame, t = q.get()
            frame = cv2.resize(frame, (640,480))
            cv2.imshow("test",frame)
            q.queue.clear()
            msg = '{:d},{:.9f}\n'.format(video_frame_id, t)
            writer.write(frame)
            f.write(msg)
            video_frame_id += 1
            if video_frame_id > total:
                dic['end'] = True
                break
            te = time.time()
            cv2.waitKey(1)
            time.sleep(max(0.001, 1. / 15 + ts - te))
        writer.release()
        f.close()
    t1 = Thread(target=get_frames, args=(q, ))
    t2 = Thread(target=save_frames, args=(q, ))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
def processing_video():
    while 1:
        print("hello")

if __name__ == '__main__':
    with Manager() as manager:
        dic=manager.dict()
        #生成一个进程间的共享字典
        dic['end']=False
        dic['exit']=False
        while True:
            key_down=cv2.waitKey(1)
            p1 = Process(target=processing_video)
            p1.start()
            if key_down==ord('q'):
                dic['end']=True
                dic['exit']=True
            p2 = Process(
                target=get_video,
                args=(dic))
            p2.start()
            p2.join()
        p1.join()