java程序员的python之路(线程)

来源:互联网 发布:什么软件测八卦 编辑:程序博客网 时间:2024/06/05 16:07

线程和进程

有时候我们需要同时执行多个任务,可以使用多线程也可以使用多进程。
进程是由若干线程组成的,一个进程至少有一个线程。线程是操作系统执行的基本单元,进程是资源的集合。每个进程都有一个单独的内存空间,是一个独立程序的一次运行活动。也就是说多个进城之间是不共享数据的。我们在windows的任务管理器中,就可以查看到很多应用的进程。线程是进程中的执行调度单位,一个进程中可以有一个或者多个线程在执行。这些线程共享进程中的所有资源。python提供了两个模块支持线程。_thread和threading._thread比较低级,一般建议使用threading。

threading线程实现

直接看代码:

import queueimport threadingimport timeclass myThread(threading.Thread):    def __init__(self,name):        threading.Thread.__init__(self)        self.name = name    def run(self):        #线程同步等待1秒钟,        time.sleep(1)        print("mythread")thread1 = myThread("hello")thread1.start()#thread1加入当前线程,  当前线程等待thread1线程执行完毕后再继续执行。thread1.join()print("mainthread")  

输出结果如下:

mythreadmainthread

线程同步

上面提到了,多个线程是共享进程的资源的。多个线程又是同时执行的。那么问题就来了
举一个经典的例子:比如你有一个银行账号里存者100块钱。你用吃完饭要用支付宝支付20元,这个支付过程分3步走,
1.1:查询账户100元
1.2:100 - 20 = 80
1.3:更改账户余额为80元

但是就是你刚执行到第2步的时候,歇了一会儿,这时候你媳妇拿着银行卡去存50元钱,也分三步走
2.1:查询账户100元
2.2:100 + 50 = 150
2.3:更改账户余额为150元

你媳妇执行到第二步的时候,也歇了一会儿,这时候你执行了第三步,然后你媳妇也执行了第三步。这时候你的银行卡里就有150块钱,你白白吃了一顿饭。
模拟代码如下:

import queueimport threadingimport time#账户类class Account():    def __init__(self,num):        self.num = num#自己class Myself(threading.Thread):    def __init__(self,account):        threading.Thread.__init__(self)        self.account = account    #消费20元    def run(self):        #查询账户余额        num = self.account.num        #支付20元        num = num - 20        #模拟歇一会儿        time.sleep(1)        #改变账户余额        self.account.num = num#媳妇       class Wife(threading.Thread):    def __init__(self,account):        threading.Thread.__init__(self)        self.account = account    #存50元        def run(self):        #查询账户余额        num = self.account.num        #存50元        num = num + 50        #模拟歇一会儿        time.sleep(2)        #改变账户余额        self.account.num = num     #创建锁       threadLock = threading.Lock()#创建账户 account = Account(100)    #创建线程thread1 = Myself(account);     thread2 = Wife(account);     thread1.start()thread2.start()#等待线程结束ts = (thread1,thread2)for t in ts:    t.join()print(account.num)

输出结果如下:

150

当然银行是不允许这种情况发生的。那么怎么解决呢?那就是你在支付的过程中,把账户锁住,不允许其他人操作此账户,待你操作完成之后,其他人才能操作。这个锁住的过程就是线程同步。修改代码:

import queueimport threadingimport time#账户类class Account():    def __init__(self,num):        self.num = num#自己class Myself(threading.Thread):    def __init__(self,account):        threading.Thread.__init__(self)        self.account = account    #消费20元    def run(self):        #加上锁        threadLock.acquire()        #查询账户余额        num = self.account.num        #支付20元        num = num - 20        #模拟歇一会儿        time.sleep(1)        #改变账户余额        self.account.num = num        #释放锁        threadLock.release()#媳妇       class Wife(threading.Thread):    def __init__(self,account):        threading.Thread.__init__(self)        self.account = account    #存50元        def run(self):        #加上锁        threadLock.acquire()        #查询账户余额        num = self.account.num        #存50元        num = num + 50        #模拟歇一会儿        time.sleep(2)        #改变账户余额        self.account.num = num             #释放锁        threadLock.release()#创建锁       threadLock = threading.Lock()#创建账户 account = Account(100)    #创建线程thread1 = Myself(account);     thread2 = Wife(account);     thread1.start()thread2.start()#等待线程结束ts = (thread1,thread2)for t in ts:    t.join()print(account.num)

输出结果如下:

130

condition

Python提供的Condition对象提供了对复杂线程同步问题的支持。Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。下面我们使用condition来实现一个线程安全的队列,使用这个队列来实现经典的生产者消费者问题。

import queueimport threadingimport time#同步队列class ConcurrentQueue():    def __init__(self,size):        self.__size = size #队列容量        self.__lock = threading.Lock() #锁        self.__condition = threading.Condition(self.__lock)        self.__queue = queue.Queue()    def get(self):        #是否获得锁成功        if self.__condition.acquire():            #如果队列为空,那么线程等待            if self.__queue.empty():                self.__condition.wait()            #取得结果                result = self.__queue._get()            #唤醒其他等待线程            self.__condition.notifyAll()            #释放锁            self.__condition.release()        return result;    def put(self,element):        #是否获得锁成功        if self.__condition.acquire():            #如果队列已满则等待            if self.__queue.qsize() >= self.__size:                self.__condition.wait()            #存入数据                self.__queue.put(element)            #唤醒其他线程            self.__condition.notifyAll()            #释放锁            self.__condition.release()#生产者class Produce(threading.Thread):    def __init__(self,queue):        threading.Thread.__init__(self)        self.__queue = queue        self.__num = 0    def run(self):        while True:            print("生产:"+str(self.__num))             self.__queue.put(self.__num)            self.__num += 1            time.sleep(2)#消费者class Consumer(threading.Thread):    def __init__(self,queue):        threading.Thread.__init__(self)        self.__queue = queue    def run(self):        while True:            element = self.__queue.get()            print("消费:"+str(element))                   time.sleep(1)q = ConcurrentQueue(10)t1 = Produce(q)         t2 = Consumer(q)   t1.start()      t2.start()

输出结果如下:

生产:0消费:0生产:1消费:1生产:2消费:2生产:3消费:3生产:4消费:4生产:5消费:5.......
原创粉丝点击