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.......
- java程序员的python之路(线程)
- java程序员的python之路(数据类型)
- java程序员的python之路(函数)
- java程序员的python之路(面向对象)
- java程序员的python之路(模块)
- java程序员的python之路(异常)
- java程序员的python之路(文件操作)
- java程序员的python之路(mongodb)
- java程序员的python之路(mongodb高级查询)
- java程序员的python之路(条件,循环和迭代器)
- 黑马程序员 【】java学习之路——线程
- 程序员的视角:java 线程
- 黑马程序员-java学习之线程
- <<黑马程序员>>java基础之线程
- 黑马程序员之java线程通信学习
- 黑马程序员之Java---线程创建方式
- 黑马程序员-------java基础之线程
- 黑马程序员——Java基础---线程的另一个总结(5)--线程池,线程定时器
- 深入研究Struts2(三)---准备Struts2的学习和开发环境
- 关于eventmachine,协程在rails里面的使用
- 单链表的测长和打印和节点查找、插入、删除、逆置
- 【图论经典题】Prison Break
- 快捷键 变量 内外类 加号重载20170719
- java程序员的python之路(线程)
- 设计模式-装饰者模式
- palindromeNumber
- Java实训第8天(面向对象)
- 访问权限修饰符(4个),继承的补充;抽象(abstract)、学习笔记
- 利用InetAddress.getByName()来产生你的IP地址
- 数据结构(第三天)栈的链式存储
- Linux硬链接和软链接
- 【solr】solr介绍