#对于io操作来说,多线程和多进程性能差别不大
#1.通过Thread类实例化 import time
import threading def get_detail_html(url):
print("get detail html started")
time.sleep(2)
print("get detail html end") def get_detail_url(url):
print("get detail url started")
time.sleep(4)
print("get detail url end") #2. 通过集成Thread来实现多线程 class GetDetailHtml(threading.Thread):
def __init__(self, name):
super().__init__(name=name) def run(self):
print("get detail html started")
time.sleep(2)
print("get detail html end") class GetDetailUrl(threading.Thread):
def __init__(self, name):
super().__init__(name=name) def run(self):
print("get detail url started")
time.sleep(4)
print("get detail url end") if __name__ == "__main__":
thread1 = GetDetailHtml("get_detail_html")
thread2 = GetDetailUrl("get_detail_url")
start_time = time.time()
thread1.start()
thread2.start() thread1.join()
thread2.join() #当主线程退出的时候, 子线程kill掉
print ("last time: {}".format(time.time()-start_time))

线程间通信 -Queue

#通过queue的方式进行线程间同步
from queue import Queue import time
import threading def get_detail_html(queue):
#爬取文章详情页
while True:
url = queue.get()
# for url in detail_url_list:
print("get detail html started")
time.sleep(2)
print("get detail html end") def get_detail_url(queue):
# 爬取文章列表页
while True:
print("get detail url started")
time.sleep(4)
for i in range(20):
queue.put("http://projectsedu.com/{id}".format(id=i))
print("get detail url end") #1. 线程通信方式- 共享变量 if __name__ == "__main__":
detail_url_queue = Queue(maxsize=1000) thread_detail_url = threading.Thread(target=get_detail_url, args=(detail_url_queue,))
for i in range(10):
html_thread = threading.Thread(target=get_detail_html, args=(detail_url_queue,))
html_thread.start()
# # thread2 = GetDetailUrl("get_detail_url")
start_time = time.time()
# thread_detail_url.start()
# thread_detail_url1.start()
#
# thread1.join()
# thread2.join()
detail_url_queue.task_done()
detail_url_queue.join() #当主线程退出的时候, 子线程kill掉
print ("last time: {}".format(time.time()-start_time))

线程锁,lock和Rlock

from threading import Lock, RLock, Condition #可重入的锁

#在同一个线程里面,可以连续调用多次acquire, 一定要注意acquire的次数要和release的次数相等
total = 0
lock = RLock()
def add():
#1. dosomething1
#2. io操作
# 1. dosomething3
global lock
global total
for i in range(1000000):
lock.acquire()
lock.acquire()
total += 1
lock.release()
lock.release() def desc():
global total
global lock
for i in range(1000000):
lock.acquire()
total -= 1
lock.release() import threading
thread1 = threading.Thread(target=add)
thread2 = threading.Thread(target=desc)
thread1.start()
thread2.start() #
thread1.join()
thread2.join()
print(total) #1. 用锁会影响性能
#2. 锁会引起死锁
#死锁的情况 A(a,b)
"""
A(a、b)
acquire (a)
acquire (b) B(a、b)
acquire (a)
acquire (b)
"""

条件变量-线程间同步

import threading

#条件变量, 用于复杂的线程间同步
# class XiaoAi(threading.Thread):
# def __init__(self, lock):
# super().__init__(name="小爱")
# self.lock = lock
#
# def run(self):
# self.lock.acquire()
# print("{} : 在 ".format(self.name))
# self.lock.release()
#
# self.lock.acquire()
# print("{} : 好啊 ".format(self.name))
# self.lock.release()
#
# class TianMao(threading.Thread):
# def __init__(self, lock):
# super().__init__(name="天猫精灵")
# self.lock = lock
#
# def run(self):
#
# self.lock.acquire()
# print("{} : 小爱同学 ".format(self.name))
# self.lock.release()
#
# self.lock.acquire()
# print("{} : 我们来对古诗吧 ".format(self.name))
# self.lock.release() #通过condition完成协同读诗 class XiaoAi(threading.Thread):
def __init__(self, cond):
super().__init__(name="小爱")
self.cond = cond def run(self):
with self.cond:
self.cond.wait()
print("{} : 在 ".format(self.name))
self.cond.notify() self.cond.wait()
print("{} : 好啊 ".format(self.name))
self.cond.notify() self.cond.wait()
print("{} : 君住长江尾 ".format(self.name))
self.cond.notify() self.cond.wait()
print("{} : 共饮长江水 ".format(self.name))
self.cond.notify() self.cond.wait()
print("{} : 此恨何时已 ".format(self.name))
self.cond.notify() self.cond.wait()
print("{} : 定不负相思意 ".format(self.name))
self.cond.notify() class TianMao(threading.Thread):
def __init__(self, cond):
super().__init__(name="天猫精灵")
self.cond = cond def run(self):
with self.cond:
print("{} : 小爱同学 ".format(self.name))
self.cond.notify()
self.cond.wait() print("{} : 我们来对古诗吧 ".format(self.name))
self.cond.notify()
self.cond.wait() print("{} : 我住长江头 ".format(self.name))
self.cond.notify()
self.cond.wait() print("{} : 日日思君不见君 ".format(self.name))
self.cond.notify()
self.cond.wait() print("{} : 此水几时休 ".format(self.name))
self.cond.notify()
self.cond.wait() print("{} : 只愿君心似我心 ".format(self.name))
self.cond.notify()
self.cond.wait() if __name__ == "__main__":
from concurrent import futures
cond = threading.Condition()
xiaoai = XiaoAi(cond)
tianmao = TianMao(cond) #启动顺序很重要
#在调用with cond之后才能调用wait或者notify方法
#condition有两层锁, 一把底层锁会在线程调用了wait方法的时候释放, 上面的锁会在每次调用wait的时候分配一把并放入到cond的等待队列中,等到notify方法的唤醒
xiaoai.start()
tianmao.start()

Semaphore 是用于控制进入数量的锁

#Semaphore 是用于控制进入数量的锁
#文件, 读、写, 写一般只是用于一个线程写,读可以允许有多个 #做爬虫
import threading
import time class HtmlSpider(threading.Thread):
def __init__(self, url, sem):
super().__init__()
self.url = url
self.sem = sem def run(self):
time.sleep(2)
print("got html text success")
self.sem.release() class UrlProducer(threading.Thread):
def __init__(self, sem):
super().__init__()
self.sem = sem def run(self):
for i in range(20):
self.sem.acquire()
html_thread = HtmlSpider("https://baidu.com/{}".format(i), self.sem)
html_thread.start() if __name__ == "__main__":
sem = threading.Semaphore(3)
url_producer = UrlProducer(sem)
url_producer.start()

多线程复习 Rlock ,Condition,Semaphore的更多相关文章

  1. 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent

    [源码下载] 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEve ...

  2. Java多线程系列——信号量:Semaphore

    简介 信号量为多线程协作提供了更为强大的控制方法.也可以说,信号量是对锁的扩展.无论是内部锁 synchronized 还是重入锁 ReentrantLock,一次都只允许一个线程访问一个资源,而信号 ...

  3. python2.7 threading RLock/Condition文档翻译 (RLock/Condition详解)

    RLock Objects 可重入锁是一个同步原语,它可以被同一个线程多次获取.在内部,除了原始锁使用的锁定/解锁状态之外,它还使用“线程拥有”和“递归级别”的概念.在锁定状态下,某些线程拥有锁:在未 ...

  4. Java多线程-新特征-信号量Semaphore

    简介信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确.合理的使用公共资源. 概念Semaphore分为单值和多值两种,前者只能 ...

  5. java多线程,多线程加锁以及Condition类的使用

    看了网上非常多的运行代码,很多都是重复的再说一件事,可能对于java老鸟来说,理解java的多线程是非常容易的事情,但是对于我这样的菜鸟来说,这个实在有点难,可能是我太菜了,网上重复的陈述对于我理解这 ...

  6. 多线程模块的condition对象

    Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方 ...

  7. 多线程条件通行工具——Semaphore

    Semaphore的作用是,限制线程通行的数量,如果线程进入时达到通行数量,便等待其它正在通行的线程释放. acquire()获取通行 release()释放通行 availablePermits() ...

  8. C# 多线程之一:信号量Semaphore

    通过使用一个计数器对共享资源进行访问控制,Semaphore构造器需要提供初始化的计数器(信号量)大小以及最大的计数器大小 访问共享资源时,程序首先申请一个向Semaphore申请一个许可证,Sema ...

  9. 多线程09-Lock和Condition

    1.概念 Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 2. ...

随机推荐

  1. Java之comparable接口

    comparable 接口: 1. 问题:java.util.Collections 类中的方法 Collections.sort(List list) 是根据什么确定容器中对象的“大小”顺序的? 2 ...

  2. java — 线程池

    线程池的作用       线程池作用就是限制系统中执行线程的数量.     根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控 ...

  3. Android中Parcelabel对象的使用和理解

    1. Parcelable接口 Interface for classes whose instances can be written to and restored from a Parcel. ...

  4. RXSwift --UITableView之初探

    对于RXSwift中的一些基本概念和说明请参看其他文章,接下来我们使用RXSwift一步一步去构建TableView,从简单到复杂.iOS开发过程中tableView的使用率是最高的,他的一些代理方法 ...

  5. c# 中base64字符串和图片的相互转换

    c#base64字符串转图片用到了bitmap类,封装 GDI+ 位图,此位图由图形图像及其特性的像素数据组成. Bitmap 是用于处理由像素数据定义的图像的对象. 具体bitmap类是什么可以自己 ...

  6. 3dContactPointAnnotationTool开发日志(八)

      今天上午去实验室打算把项目从github上pull下来发现貌似不行,然后强行pull下来后项目变得乱七八糟了,有的组件都不知道去哪里了.去github上看了看发现上面day6和day7都没有,特别 ...

  7. node.js cmd 输入npm-v无反应

    今天安装node,先是提示node版本太低.去官网更新了一下,然后 npm install -g vue-cli 结果出了个"npm ERR! errno -4048" 百度出 这 ...

  8. 使用 Python 操作 Git 版本库 - GitPython

    GitPython 是一个用于操作 Git 版本库的 python 包, 它提供了一系列的对象模型(库 - Repo.树 - Tree.提交 - Commit等) 用于操作版本库中的相应对象. 版本库 ...

  9. Java取两个变量不为空的变量的简便方法!

    一.需求 最近在项目中遇到一个小问题,即从数据库取两个变量,判断取出的变量是否为空,取不为空的变量:若两个变量都不为空,取两个变量:两个变量都为空,则跳过: 二.解决方案(这里提供两种思路) 1.第一 ...

  10. html5 canvas 图像处理

    1.图像放大缩小 <script> var cvs = document.getElementById("canvas"); cvs.width = cvs.heigh ...