python 进程创建使用,锁,阻塞和非阻塞式

 Process 类

 创建进程:
 1. p = Process(target=callable,name='',args='',kwargs='')
 2. p.start()  启动进程

 一、
 主进程:执行的时候,默认的进程称作主进程
 子进程:在主进程中可以开启子进程
        p1 = Process(target=callable,args='')
  os.getpid()  当前进程
  os.getppid()  父进程

 二、全局变量
  如果是全局变量则,每个进程都会拥有一份全局变量。各自操作各自的全局变量

 三、阻塞主进程
   子进程.join()
   阻塞主进程后面的代码



    import time
    import os
    from multiprocessing import Process
    
    
    # print('----->top:', os.getpid())
    
    def task1():
        global number
        for i in range(5):
            print('洗衣服:', i, os.getpid(), os.getppid())
            time.sleep(0.5)
        number -= 10
        print('洗衣服:', number)
    
    
    def task2(n):
        global number
        for i in range(n):
            print('劳动最光荣,扫地中...', i, os.getpid(), os.getppid())
            time.sleep(0.5)
        number -= 8
        print('扫地:', number)
    
    
    number = 100
    if __name__ == '__main__':
        print('main:--->start', os.getpid())
        p1 = Process(target=task1)
        p2 = Process(target=task2, args=(6,))
    
        p1.start()
        p2.start()
    
        # join() 加入   阻塞主进程后面的代码不执行
        p1.join()
        p2.join()
    
        print('main:--->end', os.getpid())
        print('main中的number是:', number)
进程对象可以访问方法:
run()
start()
join()
terminate()
close()  target完成之后调用的close()释放资源
is_alive()  判断target任务是否完成,如果任务完成则False,没有完成True  (是否是活动的)


    def task1():
        for i in range(5):
            print('洗衣服:', i, os.getpid(), os.getppid())
            time.sleep(0.5)
    
    
        def task2(n):
            for i in range(n):
                print('劳动最光荣,扫地中...', i, os.getpid(), os.getppid())
                time.sleep(0.5)
        
        
    # print('number:', 100)
    if __name__ == '__main__':
        p1 = Process(target=task1)
        p2 = Process(target=task2, args=(6,))
    
        # p1.run()
        # p2.run()
    
        p1.start()
        p2.start()

    for i in range(10):
        if i == 4:
            p1.terminate()  # 终止p1进程
        elif i == 5:
            p2.terminate()
        time.sleep(0.3)
        print('main:', i)

    p2.close()
    print("p1是否活着:", p1.is_alive())
    print("p2是否活着:", p2.is_alive())


 **进程池:**
    Pool

  

  **阻塞式
    非阻塞式:**
        def task1():
        
    
    print('洗衣服:', os.getpid(), os.getppid())
        time.sleep(0.5)
        return '我是进程:' + str(os.getpid())
        # response = requests.get(url)
        # return response.content
    
    
    def callback(msg):#必须传参 接受上一个函数返回的值
        print('{}洗衣服任务完成!'.format(msg))
        # 保存下载的文件到本地
    
    
        if __name__ == '__main__':
            pool = Pool(4)
        # 非阻塞式
        for i in range(10):
            pool.apply_async(task1, callback=callback)#回调函数
    # 添加任务结束
    pool.close()
    # 阻塞主进程
    pool.join()

    print('main over')


**阻塞式**

    from multiprocessing import Pool
    
    
    def task1():
        for i in range(5):
            print('洗衣服:',i, os.getpid(), os.getppid())
            time.sleep(0.5)
            # return '我是进程:' + str(os.getpid())
    
    
    if __name__ == '__main__':
        pool = Pool(4)
        #
        for i in range(10):
            pool.apply(task1) # 阻塞式: 进程池中一个任务完成之后才能做下一个任务
            print('------------------------->',i)
    
        # 添加任务结束
        pool.close()
        # 阻塞主进程
        pool.join()
    
        print('main over')



进程间通信与信号量
队列:
    FIFO

put() : 队列中存放,如果满了则阻塞
get() : 从队列中取值,如果空了则阻塞

full()  判断是否是满了
empty() 判断是否是空了  如果空了,True
qsize()  获取长度


    from multiprocessing import Process, Queue
    
    queue = Queue(3)
    
    queue.put('馒头1')
    queue.put('馒头2')
    queue.put('馒头3')
    print(queue.full())  # 判断是否满了
    print(queue)
    print(queue.qsize())
    
    try:
        queue.put('馒头4', timeout=3)
        queue.put('馒头5', timeout=3)
    except:
        print('存放馒头失败')
    
    while True:
        try:
            print(queue.get(timeout=1))
        except:
            print('队列为空,取不出东西')
            break


用process实现分进程网上下载图片:
p = Process(target=func(函数名),name='',args=(参数),kwargs={})

    def download(urls, queue):  # urls = images
        for image_url in urls:
            response = requests.get(image_url)
            image_data = response.content
            queue.put(image_data)
    
    
    def save_file(queue):
        count = 0
        while True:
            try:
                data = queue.get(timeout=5)
                # 保存到本地
                filename = 'img' + str(count) + '.jpg'
                with open('images/' + filename, 'wb') as ws:
                    ws.write(data)
    
                count += 1
                print('保存{}完毕!'.format(filename))
            except Exception as err:
                print('没有更多数据啦!')
                break
    
    
    if __name__ == '__main__':
        q1 = Queue(2)
        images = [
            'https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=7bf3ea52d40735fa85fd46ebff3864d6/8644ebf81a4c510f0912aa536059252dd52aa5a1.jpg',
            'https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=aa62e3280fb30f242197e451a9fcba26/eaf81a4c510fd9f906c11d20252dd42a2934a4a1.jpg'
        ]
        p1 = Process(target=download, args=(images, q1))
        p2 = Process(target=save_file, args=(q1,))
    
        start = time.time()  # 开始的时间戳
        p1.start()
        p2.start()

    p1.join()
    p2.join()

    end = time.time()  # 结束的时间戳

    print('用时:{}秒'.format(end - start))
  
用重写run方法实现下载图片:

      class DownloadProcess(Process):
            def __init__(self, urls, queue):
                Process.__init__(self)
                self.urls = urls
                self.queue = queue
        
            # 重写父类的run方法
            def run(self):
                for image_url in self.urls:
                    filename = os.path.split(image_url)[1]
                    response = requests.get(image_url)
                    image_data 

    = response.content
                        self.queue.put(image_
    
    data)
                    self.queue.get()
                    print('下载{}完毕'.format(filename))
                self.queue.close()
    

        
            
            if __name__ == '__main__':
                q1 = Queue(2)
                images = [
                    'https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=7bf3ea52d40735fa85fd46ebff3864d6/8644ebf81a4c510f0912aa536059252dd52aa5a1.jpg',
                    'https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6h
    
    hy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=aa62e3280fb30f242197e451a9fcba26/eaf81a4c510fd9f906c11d20252dd42a2934a4a1.jpg'
            ]
            dlprocess = DownloadProcess(images, q1)
        
            dlprocess.start()
        
        for i in range(5):
            if dlprocess.is_alive():
                print('进程是活跃的:', i)
            else:
                print('进程结束了')
                dlprocess.close()
                break
            time.sleep(0.5)


**python 如何创建一个线程?**
  **线程:**
  1.   t1 = Thread(target=task1)
  2.   自定义线程

  run()
  start()#开始
  join()#阻塞 把前面的线程运行完之后在运行
  name: 默认的Thread-1, Thread-2,....
  current_thread().name 获取当前线程的名字
  is_alive#判断是否线程还活着
'''
python 如何创建一个线程?
  线程:
  1.   t1 = Thread(target=task1)
  2.   自定义线程

  run()
  start()
  join()
  name: 默认的Thread-1, Thread-2,....
  current_thread().name 获取当前线程的名字
  is_alive
'''

    import os
    import time
    from threading import Thread,current_thread
    
    
    def task1():
        for i in range(5):
            print('{}洗衣服:'.format(current_thread().name), i, os.getpid(), os.getppid())
            time.sleep(0.5)
    
    
    def task2(n):
        for i in range(n):
            print('{}劳动最光荣,扫地中...'.format(current_thread().name), i, os.getpid(), os.getppid())
            time.sleep(0.5)
    
    
    if __name__ == '__main__':
        print('main:', os.getpid())
        # 创建线程对象
        t1 = Thread(target=task1,name='警察')
        t2 = Thread(target=task2,name='小偷', args=(6,))
        # 启动线程
        t1.start()
        t2.start()
    
        # t1.join()
        # t2.join()
    
        for i in range(3):
            print("t1:", t1.is_alive())
            print("t2:", t2.is_alive())
            print('main:', i)
            time.sleep(1)


**自定义线程:**
   1. 定义一个类继承Thread
   2. 重写: [__init__]     必须重写: run()
   3. 创建线程类对象
   4. 启动线程



    class MyThread(Thread):
        def __init__(self, name):
            Thread.__init__(self)
            self.name = name
    
        def run(self):
            for i in range(5):
                print('{}正在打印:{}'.format(self.name, i))
                time.sleep(0.1)
    
    
    if __name__ == '__main__':
        t1 = MyThread('小明')
        t2 = MyThread('小花')
        t3 = MyThread('ergou')
    
        t1.start()
        t2.start()
        t3.start()


共享数据:
如果有全局变量,则每个线程是共享的。
GIL:


    ticket = 10
    
    
    def sale_ticket():
        global ticket
        while True:
            if ticket > 0:
                print('{}正在卖第{}张火车票!'.format(current_thread().name, ticket))
                ticket -= 1
                time.sleep(1)
            else:
                break
    
    
    if __name__ == '__main__':
        t1 = Thread(target=sale_ticket, name='1号窗口')
        t2 = Thread(target=sale_ticket, name='2号窗口')
        t3 = Thread(target=sale_ticket, name='3号窗口')
    
        t1.start()
        t2.start()
        t3.start()
因为有锁的形式所以当时间大,运算量大的时候会出现不准的轻快,所以有锁的形式:

    from threading import Thread, Lock
    
    number = 0
    
    
    def task(lock):
        global number
        lock.acquire()  # 握住
        for i in range(100000):
            number += 1
        lock.release()  # 释放锁
    
    
    if __name__ == '__main__':
        lock = Lock()
        t1 = Thread(target=task, name='1号窗口', args=(lock,))
        t2 = Thread(target=task, name='2号窗口', args=(lock,))
        t3 = Thread(target=task, name='3号窗口', args=(lock,))
    
        t1.start()
        t2.start()
        t3.start()

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

    print('number:', number)

**锁:**

    from threading import Lock
    
    lock = Lock()
    
    lock.acquire()
    lock.release()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值