Day13_Process_Thread

"""
Author:黄骏捷
Date:2019-10-10

Python实现并发并发编程主要有3种方式:多进程,多线程,多进程+多线程
Unix和Linux提供了fork()系统调用来创建进程
windows系统没用fork调用,可以使用multiprocessing模块的Process类来创建子进程

使用多线程和不使用多线程的区别


#无多线程
from random import randint
from time import sleep, time


def download_task(filename):
    print('开始下载%s...' % filename)
    time_to_download = randint(5, 10)
    sleep(time_to_download)
    print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))

def main():
    start = time()
    download_task('Python入门到入土.pdf')
    download_task('Peking Hot.avi')
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))

if __name__ == '__main__':
    main()
"""

"""
多线程1
from multiprocessing import Process
from os import getpid
from random import randint
from time import sleep, time


def download_task(filename):
    print('启动下载进程,进程号[%d].' % getpid())
    print('开始下载%s...' % filename)
    time_to_download = randint(5,10)
    sleep(time_to_download)
    print('%s下载完成!耗费%d秒' % (filename,time_to_download))

def main():
    start = time()
    #Process类创建进程对象,Target参数:传入一个函数,args:函数的参数
    p1 = Process(target=download_task,args=('Python从入门到住院.pdf',))
    p1.start()
    p2 = Process(target=download_task,args=('Peking Hot.avi',))
    p2.start()
    p1.join()
    p2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))

if __name__ == '__main__':
    main()
"""


#多线程2   subprocess模块中的类和函数来创建和启动子进程,然后通过管道来和子进程通信
#一个输出Ping 一个输出Pong 加起来输出
"""
from multiprocessing import Process
from time import sleep

counter = 0

def sub_task(string):
    global counter
    while counter < 10:
        print(string,end='',flush=True)
        counter += 1
        sleep(0.01)

def main():
    Process(target=sub_task,args=('Ping',)).start()
    Process(target=sub_task,args=('Pong',)).start()

if __name__ == '__main__':
    main()

#输出 PingPongPingPongPingPongPingPongPingPongPingPongPingPongPingPongPingPongPingPong
# 当我们程序创建进程时,子进程复制了父进程及其所有数据结构,每个子进程拥有自己独立的内存空间,各有一个counter变量
"""


#多线程3 thread模块(现在名_thread)过于底层,很多功能没用,推荐使用threading模块
"""
from random import randint
from threading import Thread
from time import time, sleep


def download(filename):
    print('开始下载%s...' % filename)
    time_to_download = randint(5, 10)
    sleep(time_to_download)
    print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))


def main():
    start = time()
    t1 = Thread(target=download, args=('Python从入门到住院.pdf',))
    t1.start()
    t2 = Thread(target=download, args=('Peking Hot.avi',))
    t2.start()
    t1.join()
    t2.join()
    end = time()
    print('总共耗费了%.3f秒' % (end - start))


if __name__ == '__main__':
    main()
"""



#通过继承Thread类来创建自定义的线程类
from time import sleep, time
from random import randint
from threading import Thread

class DownloadTask(Thread):

    def __init__(self,filename):
        super().__init__()
        self._filename = filename

    def run(self):
        print('开始下载%s...' % self._filename)
        time_to_download = randint(5,10)
        sleep(time_to_download)
        print('%s下载完成!耗费了%d秒' % (self._filename,time_to_download))

def main():
    start = time()
    t1 = DownloadTask('Python从入门到住院.pdf')
    t1.start()
    t2 = DownloadTask('Peking Hot.avi')
    t2.start()
    t1.join()
    t2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()

"""
多个线程可以共享内存空间,因此多个线程间的通信相对简单,设置一个全局变量,
多个线程共享同一个变量(称为 临界资源),很可能产生不可控结果从而导致程序失效甚至崩溃

from time import sleep
from threading import Thread


class Account(object):

    def __init__(self):
        self._balance = 0

    def deposit(self, money):
        # 计算存款后的余额
        new_balance = self._balance + money
        # 模拟受理存款业务需要0.01秒的时间
        sleep(0.01)
        # 修改账户余额
        self._balance = new_balance

    @property
    def balance(self):
        return self._balance


class AddMoneyThread(Thread):

    def __init__(self, account, money):
        super().__init__()
        self._account = account
        self._money = money

    def run(self):
        self._account.deposit(self._money)


def main():
    account = Account()
    threads = []
    # 创建100个存款的线程向同一个账户中存钱
    for _ in range(100):
        t = AddMoneyThread(account, 1)
        threads.append(t)
        t.start()
    # 等所有存款的线程都执行完毕
    for t in threads:
        t.join()
    print('账户余额为: ¥%d元' % account.balance)


if __name__ == '__main__':
    main()

我们可以通过“锁”来保护“临界资源”,只有获得“锁”的线程才能访问“临界资源”,
而其他没有得到“锁”的线程只能被阻塞起来,直到获得“锁”的线程释放了“锁”,
其他线程才有机会获得“锁”,进而访问被保护的“临界资源”

from time import sleep
from threading import Thread, Lock


class Account(object):

    def __init__(self):
        self._balance = 0
        self._lock = Lock()

    def deposit(self, money):
        # 先获取锁才能执行后续的代码
        self._lock.acquire()
        try:
            new_balance = self._balance + money
            sleep(0.01)
            self._balance = new_balance
        finally:
            # 在finally中执行释放锁的操作保证正常异常锁都能释放
            self._lock.release()

    @property
    def balance(self):
        return self._balance


class AddMoneyThread(Thread):

    def __init__(self, account, money):
        super().__init__()
        self._account = account
        self._money = money

    def run(self):
        self._account.deposit(self._money)


def main():
    account = Account()
    threads = []
    for _ in range(100):
        t = AddMoneyThread(account, 1)
        threads.append(t)
        t.start()
    for t in threads:
        t.join()
    print('账户余额为: ¥%d元' % account.balance)


if __name__ == '__main__':
    main()
"""

发布了66 篇原创文章 · 获赞 45 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ACofKing/article/details/102533653